{"record":{"id":"1c2e54714da936ad","repo":"mongodb/laravel-mongodb","slug":"related-model-must-be-a-document-model","errorCode":null,"errorMessage":"Related model must be a document model.","messagePattern":"Related model must be a document model\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Relations/EmbedsOneOrMany.php","lineNumber":64,"sourceCode":"\n    /**\n     * The \"name\" of the relationship.\n     *\n     * @var string\n     */\n    protected $relation;\n\n    /**\n     * Create a new embeds many relationship instance.\n     */\n    public function __construct(Builder $query, Model $parent, Model $related, string $localKey, string $foreignKey, string $relation)\n    {\n        if (! DocumentModel::isDocumentModel($parent)) {\n            throw new LogicException('Parent model must be a document model.');\n        }\n\n        if (! DocumentModel::isDocumentModel($related)) {\n            throw new LogicException('Related model must be a document model.');\n        }\n\n        parent::__construct($query, $parent);\n\n        $this->related    = $related;\n        $this->localKey   = $localKey;\n        $this->foreignKey = $foreignKey;\n        $this->relation   = $relation;\n\n        // If this is a nested relation, we need to get the parent query instead.\n        $parentRelation = $this->getParentRelation();\n        if ($parentRelation) {\n            $this->query = $parentRelation->getQuery();\n        }\n    }\n\n    /** @inheritdoc */\n    #[Override]","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Relations/EmbedsOneOrMany.php#L46-L82","documentation":"EmbedsOneOrMany requires the RELATED model to be a MongoDB document model, since embedded documents are stored as BSON sub-documents. The constructor validates this immediately and throws a LogicException if the related class is not a DocumentModel.","triggerScenarios":"Calling embedsOne(NonDocumentModel::class) or embedsMany(NonDocumentModel::class) where the related class extends vanilla Eloquent Model, then instantiating the relation.","commonSituations":"Pointing an embeds* relation at a shared model class that was written for a SQL connection; copy-pasting relation definitions between projects.","solutions":["Make the related model extend MongoDB\\Laravel\\Eloquent\\Model","Replace the embeds* relation with belongsTo/hasMany if the related model lives in a SQL table","Check that the class passed to embedsOne/embedsMany is the intended document model"],"exampleFix":"// before\npublic function tags() { return $this->embedsMany(\\App\\Models\\Tag::class); } // Tag extends Eloquent\\Model\n// after\npublic function tags() { return $this->embedsMany(\\App\\Documents\\Tag::class); } // extends MongoDB\\Laravel\\Eloquent\\Model","handlingStrategy":"validation","validationCode":"if (!is_a($relatedClass, \\MongoDB\\Laravel\\Eloquent\\Model::class, true)) {\n    throw new \\LogicException(\"$relatedClass must extend MongoDB\\\\Laravel\\\\Eloquent\\\\Model to be embedded.\");\n}","typeGuard":"function canBeEmbedded(string $class): bool {\n    return is_a($class, \\MongoDB\\Laravel\\Eloquent\\Model::class, true);\n}","tryCatchPattern":"try {\n    $tags = $document->tags;\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'Related model must be a document model')) {\n        logger()->error('embedsMany target is not a document model');\n    }\n    throw $e;\n}","preventionTips":["Verify the class string passed to embedsOne/embedsMany extends the MongoDB Model","Document that embedded child models must be document models","Use static analysis (e.g. a custom PHPStan rule) on embeds* relation arguments"],"tags":["php","mongodb","eloquent","relations"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"0634653039468ceb0268a69192bdac64469ed043","analyzedAt":"2026-09-15T02:56:37.067Z","contentChangedAt":"2026-09-15T02:56:37.067Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}