laravel/framework · error · MassAssignmentException

Add [ ] to fillable property to allow mass assignment on […

Error message

Add [%s] to fillable property to allow mass assignment on [%s].

What it means

Thrown inside fill() when a single attribute key is not fillable AND the model is totally guarded ($guarded=['*']) OR Model::preventSilentlyDiscardingAttributes() is enabled. The check is per-key: the attribute was recognized in fillableFromArray (i.e. it is listed as fillable) but isFillable() still rejected it because the key is in $guarded, or it is not in $fillable at all under a guarded setup. This is the explicit per-attribute mass-assignment violation.

Solutions

  1. Add the named key to the model's $fillable array.
  2. If all fields are trusted, set protected $guarded = []; to disable guarding.
  3. Set the attribute directly ($model->name = $x) or use forceFill(['name' => $x]).
  4. If you only meant to update known fields, remove the stray key from the input array before fill.

Example fix

// before
class User extends Model
{
    protected $fillable = ['name', 'email'];
}
User::create(['name' => 'A', 'email' => 'b@c', 'role' => 'admin']); // throws

// after - add 'role' explicitly when intended
class User extends Model
{
    protected $fillable = ['name', 'email', 'role'];
}
Defensive patterns

Strategy: validation

Validate before calling

// Only pass attributes the model actually allows
$fillable = (new $modelClass)->getFillable();
$safe = collect($input)->only($fillable)->all();
$model->fill($safe);

Type guard

function isFillable(\Illuminate\Database\Eloquent\Model $model, string $key): bool {
    return $model->isFillable($key);
}

Try / catch

try {
    $model->fill($input);
} catch (\Illuminate\Database\Eloquent\MassAssignmentException $e) {
    // log which key was rejected, surface to user, or use forceFill if intentional
    report($e);
}

Prevention

When it happens

Trigger: Calling Model::create(['name' => $x]) (or fill/forceFill bypass) where the model has $fillable without 'name' and $guarded = ['*'] (totallyGuarded true), or where Model::preventSilentlyDiscardingAttributes() has been called and the key is being discarded.

Common situations: Adding a new column and forgetting to add it to $fillable; copying a fill array from a form request that includes a guarded field; turning on strict mode (Model::preventSilentlyDiscardingAttributes()) in tests or production to surface silent discards.

Related errors


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

Appendix: source

Thrown at src/Illuminate/Database/Eloquent/Model.php:693

     * @throws \Illuminate\Database\Eloquent\MassAssignmentException
     */
    public function fill(array $attributes)
    {
        $totallyGuarded = $this->totallyGuarded();

        $fillable = $this->fillableFromArray($attributes);

        foreach ($fillable as $key => $value) {
            // The developers may choose to place some attributes in the "fillable" array
            // which means only those attributes may be set through mass assignment to
            // the model, and all others will just get ignored for security reasons.
            if ($this->isFillable($key)) {
                $this->setAttribute($key, $value);
            } elseif ($totallyGuarded || static::preventsSilentlyDiscardingAttributes()) {
                if (isset(static::$discardedAttributeViolationCallback)) {
                    call_user_func(static::$discardedAttributeViolationCallback, $this, [$key]);
                } else {
                    throw new MassAssignmentException(sprintf(
                        'Add [%s] to fillable property to allow mass assignment on [%s].',
                        $key, get_class($this)
                    ));
                }
            }
        }

        if (count($attributes) !== count($fillable) &&
            static::preventsSilentlyDiscardingAttributes()) {
            $keys = array_diff(array_keys($attributes), array_keys($fillable));

            if (isset(static::$discardedAttributeViolationCallback)) {
                call_user_func(static::$discardedAttributeViolationCallback, $this, $keys);
            } else {
                throw new MassAssignmentException(sprintf(
                    'Add fillable property [%s] to allow mass assignment on [%s].',
                    implode(', ', $keys),
                    get_class($this)

View on GitHub (pinned to e0f6eb3518)