laravel/framework · error · InvalidArgumentException

The cast object for the

Error message

The cast object for the {$attribute} attribute must implement Stringable.

What it means

Thrown by ensureCastsAreStringValues() when a cast entry is an object that does not implement Stringable. When casts are merged/resolved, Laravel normalizes each cast to a string form (e.g. 'ClassName:arg1,arg2'); an object that cannot be cast to string via __toString breaks that normalization, so it is rejected with an explicit error.

Solutions

  1. Implement \Stringable on the caster class and add __toString() returning the cast string (e.g. the class name).
  2. Use the class name string (e.g. SomeCaster::class) in $casts instead of an instance.
  3. If using a class-based cast, register it via the Castable infrastructure or as 'classname:args'.

Example fix

// before
protected $casts = [
    'settings' => new App\Casts\SettingsCast, // not Stringable
];

// after
class SettingsCast implements \Stringable
{
    public function __toString(): string
    {
        return static::class;
    }
}

protected $casts = [
    'settings' => new App\Casts\SettingsCast,
];
Defensive patterns

Strategy: validation

Validate before calling

foreach ((function () { $m = new YourModel; $r = new \ReflectionObject($m); return $r->getProperty('casts')->getValue($m); })() as $attr => $cast) {
    if (is_object($cast) && ! ($cast instanceof \Stringable)) {
        throw new \LogicException("Cast for {$attr} must implement Stringable");
    }
}

Type guard

function castObjectIsStringable(mixed $cast): bool
{
    return is_object($cast) && $cast instanceof \Stringable;
}

Prevention

When it happens

Trigger: Assigning a non-Stringable object instance to $casts (e.g. protected $casts = ['data' => new SomeCaster];) where SomeCaster does not implement \Stringable. Triggered when casts are processed/merged (e.g. via mergeCasts / hasCasts / getCasts).

Common situations: Passing a custom caster class instance (instead of its class name) that was not marked Stringable; third-party cast package whose object form predates the Stringable requirement; refactoring casts from strings to object instances during an upgrade.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/a892d5115c296943. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:821

    /**
     * Ensure that the given casts are strings.
     *
     * @param  array  $casts
     * @return array
     *
     * @throws \InvalidArgumentException
     */
    protected function ensureCastsAreStringValues($casts)
    {
        foreach ($casts as $attribute => $cast) {
            $casts[$attribute] = match (true) {
                is_object($cast) => value(function () use ($cast, $attribute) {
                    if ($cast instanceof Stringable) {
                        return (string) $cast;
                    }

                    throw new InvalidArgumentException(
                        "The cast object for the {$attribute} attribute must implement Stringable."
                    );
                }),
                is_array($cast) => value(function () use ($cast) {
                    if (count($cast) === 1) {
                        return $cast[0];
                    }

                    [$cast, $arguments] = [array_shift($cast), $cast];

                    return $cast.':'.implode(',', $arguments);
                }),
                default => $cast,
            };
        }

        return $casts;
    }

View on GitHub (pinned to e0f6eb3518)