{"record":{"id":"4b8b4778a91dfb0b","repo":"symfony/var-dumper","slug":"s-object-holds-non-iterable-type-s","errorCode":null,"errorMessage":"\"%s\" object holds non-iterable type \"%s\".","messagePattern":"\"(.+?)\" object holds non-iterable type \"(.+?)\"\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"Cloner/Data.php","lineNumber":118,"sourceCode":"                    }\n                    $recursive[$v->position] = true;\n                }\n                $children[$k] = $children[$k]->getValue($recursive);\n            }\n        }\n\n        return $children;\n    }\n\n    public function count(): int\n    {\n        return \\count($this->getValue());\n    }\n\n    public function getIterator(): \\Traversable\n    {\n        if (!\\is_array($value = $this->getValue())) {\n            throw new \\LogicException(\\sprintf('\"%s\" object holds non-iterable type \"%s\".', self::class, get_debug_type($value)));\n        }\n\n        yield from $value;\n    }\n\n    public function __get(string $key): mixed\n    {\n        if (null !== $data = $this->seek($key)) {\n            $item = $this->getStub($data->data[$data->position][$data->key]);\n\n            return $item instanceof Stub || [] === $item ? $data : $item;\n        }\n\n        return null;\n    }\n\n    public function __isset(string $key): bool\n    {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/symfony/var-dumper/blob/e9d9cf5dcdd4b1b13b4504aaffd66ce4ddb5684e/Cloner/Data.php#L100-L136","documentation":"Data::getIterator() implements Traversable over the underlying value, but only when that value is an array. Calling it on a Data wrapping a scalar, string, or other non-array type throws a LogicException because iteration is meaningless for those values.","triggerScenarios":"foreach over a Data object whose wrapped value is not an array, e.g. `foreach ($cloned->data as ...)` where the cloned value is a string, int, null, or object.","commonSituations":"Treating a dumped/cloned variable as always iterable; var-dumper clone results where the top-level value is scalar; code assuming dump output shape without checking the value type first.","solutions":["Check the value type before iterating: call $data->getValue() and is_array() it, or use $data->count()/type()","Only iterate Data objects that wrap arrays; use ->getValue() for scalars","If the value may be scalar, wrap iteration in an is_array guard"],"exampleFix":"// before\nforeach ($data as $k => $v) { ... }\n// after\n$value = $data->getValue();\nif (is_array($value)) {\n    foreach ($value as $k => $v) { ... }\n}","handlingStrategy":"type-guard","validationCode":"$value = $data->getValue();\nif (!is_array($value)) {\n    throw new \\LogicException('Expected array value, got '.get_debug_type($value));\n}","typeGuard":"function isIterableData(\\Symfony\\Component\\VarDumper\\Cloner\\Data $data): bool {\n    return is_array($data->getValue());\n}","tryCatchPattern":"try {\n    foreach ($data as $k => $v) { /* ... */ }\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'non-iterable')) {\n        // handle scalar: use $data->getValue() directly\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Check $data->getValue() type (or ->getType()) before iterating","Only feed Data objects wrapping arrays into foreach loops","Copy out clone results with an is_array check before iteration"],"tags":["iteration","type-error","var-dumper"],"backgroundTag":"incompatible-source-type","analyzedSha":"e9d9cf5dcdd4b1b13b4504aaffd66ce4ddb5684e","analyzedAt":"2026-09-14T11:19:53.665Z","contentChangedAt":"2026-09-14T11:19:53.665Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}