{"id":"fe1ac43dbd44f93c","repo":"laravel/framework","slug":"s-s-must-return-a-relationship-instance-but-n","errorCode":null,"errorMessage":"%s::%s must return a relationship instance, but \"null\" was returned. Was the \"return\" keyword used?","messagePattern":"(.+?)::(.+?) must return a relationship instance, but \"null\" was returned\\. Was the \"return\" keyword used\\?","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php","lineNumber":641,"sourceCode":"\n        throw new LazyLoadingViolationException($this, $key);\n    }\n\n    /**\n     * Get a relationship value from a method.\n     *\n     * @param  string  $method\n     * @return mixed\n     *\n     * @throws \\LogicException\n     */\n    protected function getRelationshipFromMethod($method)\n    {\n        $relation = Relation::withConstraintsForNestedRelation(fn () => $this->$method());\n\n        if (! $relation instanceof Relation) {\n            if (is_null($relation)) {\n                throw new LogicException(sprintf(\n                    '%s::%s must return a relationship instance, but \"null\" was returned. Was the \"return\" keyword used?', static::class, $method\n                ));\n            }\n\n            throw new LogicException(sprintf(\n                '%s::%s must return a relationship instance.', static::class, $method\n            ));\n        }\n\n        return tap($relation->getResults(), function ($results) use ($method) {\n            $this->setRelation($method, $results);\n        });\n    }\n\n    /**\n     * Determine if a get mutator exists for an attribute.\n     *\n     * @param  string  $key","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L623-L659","documentation":"getRelationshipFromMethod() calls the relation method and checks the result. If it returns exactly null, the most common cause is a missing 'return' keyword inside the method body, so the framework's hint message points at that exact mistake.","triggerScenarios":"Defining a relation method without 'return': public function comments() { $this->hasMany(Comment::class); } and then accessing $model->comments.","commonSituations":"Copy-paste error omitting 'return'; IDE auto-format that drops the keyword; refactoring a method body and forgetting to keep the return; static analyzers (phpstan) not yet run on the file.","solutions":["Add the missing 'return' before the relation builder call.","Run phpstan/pint locally; configure larastan to flag missing returns.","Double-check every method that returns HasMany/BelongsTo etc. ends with 'return $this->...'."],"exampleFix":"// before\npublic function comments()\n{\n    $this->hasMany(Comment::class); // no return\n}\n\n// after\npublic function comments()\n{\n    return $this->hasMany(Comment::class);\n}","handlingStrategy":"type-guard","validationCode":"// Static analysis is the real guard; at runtime, inspect the method\n$ref = new \\ReflectionMethod($model, $relation);\nif (! str_contains((string) $ref->getBodyText() ?? '', 'return')) {\n    throw new \\LogicException(\"{$relation}() may be missing 'return'\");\n}","typeGuard":"function relationReturnsInstance(object $model, string $method): bool\n{\n    $r = $model->{$method}();\n    return $r instanceof \\Illuminate\\Database\\Eloquent\\Relations\\Relation;\n}","tryCatchPattern":"try {\n    return $model->{$relation};\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), '\"null\" was returned')) {\n        // tell developer to add 'return' in the relation method\n    }\n    throw $e;\n}","preventionTips":["Run Larastan/phpstan level 6+ to catch missing returns statically.","Every relation method must end with 'return $this->...Relation(...)'.","Add a unit test that asserts each relation method returns a Relation instance."],"tags":["eloquent","relationship","developer-error","return-keyword"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}