{"id":"d8d560faab695df9","repo":"laravel/framework","slug":"s-s-must-return-a-relationship-instance","errorCode":null,"errorMessage":"%s::%s must return a relationship instance.","messagePattern":"(.+?)::(.+?) must return a relationship instance\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php","lineNumber":646,"sourceCode":"     * 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\n     * @return bool\n     */\n    public function hasGetMutator($key)\n    {\n        return method_exists($this, 'get'.Str::studly($key).'Attribute');","sourceCodeStart":628,"sourceCodeEnd":664,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L628-L664","documentation":"Same method as 148, but the relation returned a non-null value that is not a Relation instance (e.g. a Builder, Collection, Model, or scalar). Eloquent can only hydrate from a real Relation, so it refuses.","triggerScenarios":"A relation method that returns $this->hasMany(...)->where(...) when chained into a Builder, returns ->get() (a Collection), returns ->first() (a Model), or returns an arbitrary value; then accessing the relation triggers the error.","commonSituations":"Chaining ->get()/->first() inside the relation method; returning a query-scope result; refactoring that returned the wrong builder type; conditional return paths that return mixed types.","solutions":["Return only the Relation instance: return $this->hasMany(Comment::class); move ->where() into a scope or caller.","If you need constraints, define them via a closure passed to hasMany/hasOne: $this->hasMany(Comment::class)->where('active', 1).","For computed data, expose a separate accessor method, not a relation method."],"exampleFix":"// before\npublic function activeComments()\n{\n    return $this->hasMany(Comment::class)->where('active', 1)->get();\n}\n\n// after\npublic function activeComments()\n{\n    return $this->hasMany(Comment::class)->where('active', 1);\n}","handlingStrategy":"type-guard","validationCode":"$r = $model->{$relation}();\nif (! $r instanceof \\Illuminate\\Database\\Eloquent\\Relations\\Relation) {\n    throw new \\LogicException(get_class($model) . '::' . $relation . ' returned ' . get_debug_type($r));\n}","typeGuard":"function isRelationMethod(object $model, string $method): bool\n{\n    return $model->{$method}() instanceof \\Illuminate\\Database\\Eloquent\\Relations\\Relation;\n}","tryCatchPattern":"try {\n    return $model->{$relation};\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'must return a relationship instance')) {\n        report(get_class($model) . '::' . $relation . ' returns a non-Relation');\n    }\n    throw $e;\n}","preventionTips":["Do not chain ->get()/->first() inside relation methods; chain query constraints only.","Use Larastan to flag methods declared as Relation that return other types.","Cover each relation with a test asserting the return type."],"tags":["eloquent","relationship","developer-error","type-error"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}