laravel/framework · error · LazyLoadingViolationException
Attempted to lazy load [{$relation}] on model [{$class}] but
Error message
Attempted to lazy load [{$relation}] on model [{$class}] but lazy loading is disabled. What it means
When Model::preventLazyLoading() is enabled, accessing a relationship that has not been eager-loaded triggers LazyLoadingViolationException. This is the framework's N+1 protection: it forces developers to load relations via with()/load() instead of firing a query per access.
Source
Thrown at src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:624
/**
* Handle a lazy loading violation.
*
* @param string $key
* @return mixed
*
* @throws \Illuminate\Database\LazyLoadingViolationException
*/
protected function handleLazyLoadingViolation($key)
{
if (isset(static::$lazyLoadingViolationCallback)) {
return call_user_func(static::$lazyLoadingViolationCallback, $this, $key);
}
if (! $this->exists || $this->wasRecentlyCreated) {
return;
}
throw new LazyLoadingViolationException($this, $key);
}
/**
* Get a relationship value from a method.
*
* @param string $method
* @return mixed
*
* @throws \LogicException
*/
protected function getRelationshipFromMethod($method)
{
$relation = Relation::withConstraintsForNestedRelation(fn () => $this->$method());
if (! $relation instanceof Relation) {
if (is_null($relation)) {
throw new LogicException(sprintf(
'%s::%s must return a relationship instance, but "null" was returned. Was the "return" keyword used?', static::class, $methodView on GitHub (pinned to bd6b5437e6)
Solutions
- Eager-load the relation: Post::with('comments')->first().
- Lazy-load explicitly where allowed: $post->load('comments') before access.
- If intentional, register a lazyLoadingViolationCallback via Model::handleLazyLoadingViolationUsing() to log instead of throw.
Example fix
// before
$post = Post::first();
$post->comments; // throws when preventLazyLoading is on
// after
$post = Post::with('comments')->first();
$post->comments; Defensive patterns
Strategy: validation
Validate before calling
// Ensure relations are loaded before access
foreach (['comments', 'author'] as $rel) {
if (! $post->relationLoaded($rel)) {
$post->load($rel);
}
} Type guard
function relationSafe(\Illuminate\Database\Eloquent\Model $m, string $rel): bool
{
return $m->relationLoaded($rel) || ! $m->isRelation($rel);
} Try / catch
try {
return $post->comments;
} catch (\Illuminate\Database\LazyLoadingViolationException $e) {
$post->load($e->relation);
return $post->{$e->relation};
} Prevention
- Eager-load relations at query time with with().
- Keep preventLazyLoading enabled in non-production to find N+1s early.
- Use a lazyLoadingViolation callback (Model::handleLazyLoadingViolationUsing) to log instead of throw in prod.
When it happens
Trigger: Enabling preventLazyLoading (default true in many Laravel test bootstraps) then doing $post = Post::first(); $post->comments; without ->with('comments'). Also fires for first()/all()/find() queries that omit the needed relation.
Common situations: Forgetting with() when serializing resources or API responses; looping over a collection and touching a relation; new team member not aware eager loading is required; serialization (toArray) of unloaded relations.
Related errors
- %s::%s must return a relationship instance, but "null" was r
- %s::%s must return a relationship instance.
- No morph map defined for model [{$class}].
- The chunkById operation was aborted because the [{$alias}] c
- The lazyById operation was aborted because the [{$alias}] co
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/521b47f7114adb5a.json.
Report an issue: GitHub.