laravel/framework · error · MassAssignmentException

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

Error message

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

What it means

Thrown by Model::fill() at the post-loop check: when the number of provided attributes differs from those accepted via fillableFromArray() AND preventsSilentlyDiscardingAttributes() is on. Unlike the per-key form, this fires once listing all keys that were entirely filtered out (e.g. because they were in $guarded). The message lists every discarded key and the class.

Source

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

                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)
                ));
            }
        }

        return $this;
    }

    /**
     * Fill the model with an array of attributes. Force mass assignment.
     *
     * @param  array<string, mixed>  $attributes
     * @return $this
     */
    public function forceFill(array $attributes)
    {

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Remove the offending keys from the input array before calling fill()/create() (e.g. via $request->only(...)).
  2. Add the keys to $fillable (and remove from $guarded) if they should be mass-assignable.
  3. Use forceFill() when intentionally bypassing guards for those specific keys.
  4. Disable preventSilentlyDiscardingAttributes() in contexts where silent discard is acceptable.

Example fix

// before
Model::preventSilentlyDiscardingAttributes();
User::create($request->all()); // $request has guarded 'is_admin'

// after
User::create($request->only(['name', 'email']));
Defensive patterns

Strategy: validation

Validate before calling

$instance = new $modelClass;
$accepted = $instance->fillableFromArray($input);
if (count($input) !== count($accepted) && \Illuminate\Database\Eloquent\Model::preventsSilentlyDiscardingAttributes()) {
    // some keys are guarded; restrict input before fill
    $input = array_intersect_key($input, array_flip($instance->getFillable()));
}
$instance->fill($input);

Try / catch

try {
    $model->fill($input);
} catch (\Illuminate\Database\Eloquent\MassAssignmentException $e) {
    // log discarded keys, then forceFill or restrict input
}

Prevention

When it happens

Trigger: Model::preventSilentlyDiscardingAttributes() is enabled globally and you call create()/fill()/update() with keys present in $guarded (or absent from a non-empty $fillable), so fillableFromArray() drops them and the counts diverge.

Common situations: Turning on strict mass-assignment discarding in dev/test; configuring $guarded with specific columns then attempting to mass-assign one of them; payloads from requests including guarded fields.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/9bc7253a285b8365.json. Report an issue: GitHub.