{"id":"441115bb3b2dc1f7","repo":"laravel/framework","slug":"model-attribute-value-is-an-object-but-does-not-ha","errorCode":null,"errorMessage":"Model attribute value is an object but does not have a __toString method.","messagePattern":"Model attribute value is an object but does not have a __toString method\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithDictionary.php","lineNumber":35,"sourceCode":"     *\n     * @throws \\InvalidArgumentException\n     */\n    protected function getDictionaryKey($attribute)\n    {\n        if (is_null($attribute) || is_string($attribute) || is_int($attribute)) {\n            return $attribute;\n        }\n\n        if (is_object($attribute)) {\n            if (method_exists($attribute, '__toString')) {\n                return $attribute->__toString();\n            }\n\n            if ($attribute instanceof UnitEnum) {\n                return enum_value($attribute);\n            }\n\n            throw new InvalidArgumentException('Model attribute value is an object but does not have a __toString method.');\n        }\n\n        return (string) $attribute;\n    }\n}\n","sourceCodeStart":17,"sourceCodeEnd":41,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithDictionary.php#L17-L41","documentation":"InteractsWithDictionary::getDictionaryKey() builds the keys used to match related models when loading relations. Strings/ints/null pass through, objects with __toString or UnitEnum are converted, but any other object is rejected with InvalidArgumentException because it cannot become a stable dictionary key.","triggerScenarios":"Loading a relation where a key/foreign-key attribute holds an arbitrary object (e.g. a Carbon instance, a DTO, or a stdClass) that has no __toString and is not a UnitEnum; casting a key to an object inadvertently.","commonSituations":"Custom casts that return an object for a column used as a key; passing a model as a key value; storing non-scalar primary keys; enum-backed keys where the enum cast is misconfigured.","solutions":["Ensure key/foreign-key columns cast to scalar string/int (use a string/integer cast, not an object cast).","Implement __toString on the object type if it legitimately represents a key, or use a backed enum (UnitEnum) for enum keys.","Pass the scalar key value instead of an object when matching relations."],"exampleFix":"// before\n// a custom cast returns an Amount object for the 'currency' key column\n// -> throws during relation load\n\n// after\nclass Amount { public function __toString(): string { return (string) $this->value; } }\n// or cast the key as 'string':\nprotected $casts = ['currency' => 'string'];","handlingStrategy":"type-guard","validationCode":"foreach ($keys as $key) {\n    if (is_object($key) && ! method_exists($key, '__toString') && ! ($key instanceof \\UnitEnum)) {\n        throw new \\InvalidArgumentException('Key object lacks __toString: '.get_class($key));\n    }\n}","typeGuard":"function isDictionaryKeyable(mixed $key): bool {\n    return is_null($key) || is_string($key) || is_int($key)\n        || (is_object($key) && (method_exists($key, '__toString') || $key instanceof \\UnitEnum));\n}","tryCatchPattern":null,"preventionTips":["Keep key/foreign-key columns cast to scalar string/int.","Implement __toString or use backed enums for object keys.","Avoid custom object casts on columns used as relation keys."],"tags":["eloquent","relationships","dictionary","casts","tostring"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}