laravel/framework · error · MassAssignmentException

Add [%s] 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 by Model::fill() when mass-assigning an attribute that is not in $fillable (and not in $guarded allow-list), and the model is either totally guarded ($guarded=['*'] with empty fillable) or the app has Model::preventSilentlyDiscardingAttributes() enabled. The per-key form fires inside the loop for each offending attribute; the message names the specific key and class.

Source

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

     * @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 bd6b5437e6)

Solutions

  1. Add the attribute to the model's $fillable array (protected $fillable = ['...', 'role'];).
  2. Assign the attribute directly ($user->role = 'admin'; $user->save()) if it should not be mass-assignable.
  3. Use forceFill(['role' => 'admin']) when you intentionally bypass guard checks.
  4. Audit $guarded and ensure the attribute is not in the guard list, or switch from guarded to explicit fillable.

Example fix

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

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

Strategy: validation

Validate before calling

$fillable = (new $modelClass)->getFillable();
$unknown = array_diff(array_keys($input), $fillable);
if ($unknown) {
    throw new \InvalidArgumentException('Unknown mass-assignable keys: '.implode(',', $unknown));
}
$modelClass::create($input);

Type guard

function isMassAssignable($model, string $key): bool {
    return in_array($key, $model->getFillable(), true) || $model->isGuardableColumn($key) && ! $model->isGuarded($key);
}

Prevention

When it happens

Trigger: new User(['role' => 'admin']) or User::create(['role' => 'admin']) where 'role' is not in the User::$fillable array and the model is totally guarded or discarding protection is on.

Common situations: Adding a new column/attribute and forgetting to add it to $fillable; using guarded-only models; enabling preventSilentlyDiscardingAttributes() in tests/non-prod which turns previously-silent discards into exceptions.

Related errors


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