laravel/framework · error · MissingAttributeException
The attribute [%s] either does not exist or was not retrieve
Error message
The attribute [%s] either does not exist or was not retrieved for model [%s].
What it means
When Model::preventAccessingMissingAttributes() is enabled (strict mode), accessing an attribute that is neither in the attributes array nor a relation/relation-resolver raises MissingAttributeException. This catches silent null returns caused by SELECTing a subset of columns while accessing unselected attributes.
Source
Thrown at src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:527
/**
* Either throw a missing attribute exception or return null depending on Eloquent's configuration.
*
* @param string $key
* @return null
*
* @throws \Illuminate\Database\Eloquent\MissingAttributeException
*/
protected function throwMissingAttributeExceptionIfApplicable($key)
{
if ($this->exists &&
! $this->wasRecentlyCreated &&
static::preventsAccessingMissingAttributes()) {
if (isset(static::$missingAttributeViolationCallback)) {
return call_user_func(static::$missingAttributeViolationCallback, $this, $key);
}
throw new MissingAttributeException($this, $key);
}
return null;
}
/**
* Get a plain attribute (not a relationship).
*
* @param string $key
* @return mixed
*/
public function getAttributeValue($key)
{
return $this->transformModelValue($key, $this->getAttributeFromArray($key));
}
/**
* Get an attribute from the $attributes array.View on GitHub (pinned to bd6b5437e6)
Solutions
- Add the missing column to the query: ->select('id', 'title') or ->addSelect('title').
- Use ->withColumns() / ensure full row hydration by removing over-restrictive select().
- Confirm the attribute name spelling and that the column exists in the table/migration.
Example fix
// before
Model::preventAccessingMissingAttributes(true);
$post = Post::select('id')->first();
echo $post->title; // throws
// after
$post = Post::select('id', 'title')->first();
echo $post->title; Defensive patterns
Strategy: validation
Validate before calling
// Before strict access, ensure columns are present
$cols = ['id', 'title']; // required
$row = Post::select($cols)->first();
foreach ($cols as $c) {
if (! array_key_exists($c, $row->getAttributes())) {
throw new \RuntimeException("Column {$c} not selected");
}
} Type guard
function hasAttributeSelected(\Illuminate\Database\Eloquent\Model $m, string $key): bool
{
return array_key_exists($key, $m->getAttributes())
|| $m->hasGetMutator($key)
|| $m->hasCast($key);
} Try / catch
try {
return $model->{$key};
} catch (\Illuminate\Database\Eloquent\MissingAttributeException $e) {
report("Missing attribute {$key} on ".get_class($model));
return null;
} Prevention
- Keep select() lists in sync with attributes touched by serializers/views.
- Enable preventAccessingMissingAttributes in tests to catch regressions early.
- Prefer $model->only([...]) with whitelisted fields when hydrating partial rows.
When it happens
Trigger: Enabling strict attribute access (often in tests via Model::preventAccessingMissingAttributes(true)) then doing SomeModel::select('id')->first()->title, where 'title' was not in the SELECT list. Also fires for genuinely misspelled attribute names.
Common situations: Strict-mode enabled globally in TestCase; using select() or addSelect() that omits a column later read by a view/serializer; column renamed in migration but code not updated; using ->only([...]) with a fresh model.
Related errors
- Add fillable property [%s] to allow mass assignment on [%s].
- The chunkById operation was aborted because the [{$alias}] c
- The lazyById operation was aborted because the [{$alias}] co
- No record found for the given query.
- $count records were found.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/502138c175110d3f.json.
Report an issue: GitHub.