#20519·filament

`$get()` returns raw (uncast) state when called from the field's parent container, but cast state from a sibling

Author: sawirricardoCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbugunconfirmedmedium priority

Package

filament/schemas

Package Version

v5.8.2

Laravel Version

v13.32.0

Livewire Version

v4.4.5

PHP Version

PHP 8.5.10

Problem description

$get('field') returns a different type depending on which component calls it, when the target field has a state cast (e.g. a Select with ->options(SomeEnum::class), which registers EnumStateCast).

  • Called from a closure on a sibling container (e.g. another Tab's badge() / visible()), $get('status') finds the Select and returns $component->getState(), i.e. the enum instance.
  • Called from a closure on the parent container of that field (e.g. the Tab that holds the Select), $get('status') returns the raw string value.

Cause: Get::__invoke() pushes the calling component onto skipComponentsChildContainersWhileSearching before searching, so the search never descends into the caller's own children. When the field isn't found it falls back to data_get($livewire, $path), which reads the raw Livewire state and bypasses the field's state casts.

Skipping the caller's children is presumably intentional (to avoid recursing into children that aren't built yet), but the fallback silently changing the returned type is surprising. The same $get('status') === Status::Published comparison is true in one closure and false in another, and (string) $get('status') throws in one place and works in another.

Where the behaviour comes from (packages/schemas/src/Components/Utilities/Get.php):

php
static::$skipComponentsChildContainersWhileSearching[] = $this->component;

$component = ($this->component->getStatePath() === $path)
    ? $this->component
    : $this->component->getRootContainer()->getComponentByStatePath(
        $path,
        withHidden: true,
        withAbsoluteStatePath: true,
        skipComponentsChildContainersWhileSearching: /* includes the caller */,
    );

if (! $component) {
    return data_get($livewire, $path); // raw, uncast
}

return $component->getState(); // cast

Expected behavior

$get() should return the same type for the same path regardless of which component the closure is attached to. Either the fallback should still apply the target field's state casts, or (if that's not feasible) the docs should state that $get() from a parent container returns raw, uncast state.

Steps to reproduce

Minimal page (full code in the reproduction repo):

php
enum Status: string
{
    case Draft = 'draft';
    case Published = 'published';
}

// In a page/form schema, with state filled as ['status' => 'published']:
Tabs::make()->tabs([
    Tab::make('Parent tab')
        ->badge(fn (Get $get): string => get_debug_type($get('status'))) // "string"
        ->schema([
            Select::make('status')->options(Status::class),
        ]),

    Tab::make('Sibling tab')
        ->badge(fn (Get $get): string => get_debug_type($get('status'))) // "App\Enums\Status"
        ->schema([]),
]),
  1. git clone https://github.com/sawirricardo/filament-get-cast-repro && cd filament-get-cast-repro && composer setup
  2. php artisan test tests/Feature/GetCastTest.php

The test asserts both badges report the same type and fails with:

- 'Parent tab' => 'App\Enums\Status',
+ 'Parent tab' => 'string',
  'Sibling tab' => 'App\Enums\Status',

Alternatively log in at /admin and open Get Cast Page: the two tab badges show string and App\Enums\Status for the same call.

Reproduction repository (issue will be closed if this is not valid)

https://github.com/sawirricardo/filament-get-cast-repro

Relevant log output

bash
$ php artisan test tests/Feature/GetCastTest.php

FAILED  Tests\Feature\GetCastTest > get returns the same type regardless of which component calls it
Failed asserting that two arrays are identical.
--- Expected
+++ Actual
@@ @@
 Array &0 [
-    'Parent tab' => 'App\Enums\Status',
+    'Parent tab' => 'string',
     'Sibling tab' => 'App\Enums\Status',
 ]

at tests/Feature/GetCastTest.php:24

Tests:  1 failed (1 assertions)