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
- Add the named key to the model's $fillable array.
- If all fields are trusted, set protected $guarded = []; to disable guarding.
- Set the attribute directly ($model->name = $x) or use forceFill(['name' => $x]).
- 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
- Keep $fillable in sync with migrations and form requests - add a column, update the array.
- Use Model::preventSilentlyDiscardingAttributes() in non-production to catch missing fillable entries early.
- In controllers, intersect request input with $model->getFillable() before fill().
- Prefer explicit $fillable over $guarded=[] unless you fully trust all input.
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
- Add fillable property
- Could not verify the hashed value's configuration.
- Call to undefined cast
- Call to undefined method
- Cannot use saveOrIgnore on an existing model.
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)