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, $method

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Eager-load the relation: Post::with('comments')->first().
  2. Lazy-load explicitly where allowed: $post->load('comments') before access.
  3. 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

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


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