{"record":{"id":"7844ffe94156c425","repo":"doctrine/orm","slug":"roottypewalker-is-to-be-used-on-selectstatements-o","errorCode":null,"errorMessage":"RootTypeWalker is to be used on SelectStatements only","messagePattern":"RootTypeWalker is to be used on SelectStatements only","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Tools/Pagination/RootTypeWalker.php","lineNumber":55,"sourceCode":"        }\n\n        $fromRoot            = reset($from);\n        $rootAlias           = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;\n        $rootClass           = $this->getMetadataForDqlAlias($rootAlias);\n        $identifierFieldName = $rootClass->getSingleIdentifierFieldName();\n\n        return PersisterHelper::getTypeOfField(\n            $identifierFieldName,\n            $rootClass,\n            $this->getQuery()\n                ->getEntityManager(),\n        )[0];\n    }\n\n    public function getFinalizer(AST\\DeleteStatement|AST\\UpdateStatement|AST\\SelectStatement $AST): SqlFinalizer\n    {\n        if (! $AST instanceof AST\\SelectStatement) {\n            throw new RuntimeException(self::class . ' is to be used on SelectStatements only');\n        }\n\n        return new PreparedExecutorFinalizer(new FinalizedSelectExecutor($this->walkSelectStatement($AST)));\n    }\n}\n","sourceCodeStart":37,"sourceCodeEnd":61,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Tools/Pagination/RootTypeWalker.php#L37-L61","documentation":"RootTypeWalker resolves the root entity's identifier type and only makes sense for SELECT statements; its getFinalizer() (the ORM 3 SQL-generation API called after walking) guards that the AST is a SelectStatement and throws otherwise. Doctrine's Paginator only attaches RootTypeWalker to SELECT queries, so in practice this fires when application code manually sets Query::HINT_CUSTOM_OUTPUT_WALKER to RootTypeWalker (an internal class) on an UPDATE or DELETE DQL statement.","triggerScenarios":"$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, RootTypeWalker::class) followed by execute()/executeUpdate() on a DQL UPDATE or DELETE; or reusing/cloning a query object that still carries the Paginator's RootTypeWalker hint and changing its DQL to an update/delete.","commonSituations":"Copying Paginator internals into application code; a shared/cloned query object reused for different statement types; generic listener code that sets output-walker hints on every query it sees.","solutions":["Remove the manual RootTypeWalker hint - it is internal to Paginator and must not be set by user code.","If you need the root identifier type, call PersisterHelper::getTypeOfField($class->getSingleIdentifierFieldName(), $class, $em) directly.","If you set HINT_CUSTOM_OUTPUT_WALKER generically, first verify the statement is a SELECT via $query->getAST()."],"exampleFix":"// before\nuse Doctrine\\ORM\\Tools\\Pagination\\RootTypeWalker;\n$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, RootTypeWalker::class);\n$query->execute(); // UPDATE statement -> RuntimeException\n\n// after\nuse Doctrine\\ORM\\Utility\\PersisterHelper;\n$type = PersisterHelper::getTypeOfField($class->getSingleIdentifierFieldName(), $class, $em)[0];","handlingStrategy":"validation","validationCode":"// Only attach a custom output walker to SELECT statements\nuse Doctrine\\ORM\\Query\\AST\\SelectStatement;\n\nif ($query->getAST() instanceof SelectStatement) {\n    $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, $walkerClass);\n} else {\n    throw new InvalidArgumentException('Custom output walkers apply to SELECT queries only');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never reference internal walker classes (RootTypeWalker) from application code","Do not reuse/cloning query objects across different statement types with hints attached","Resolve field types with the public PersisterHelper API instead of walker hacks"],"tags":["doctrine-orm","walker","custom-output-walker","internal-api","select-only","dql"],"backgroundTag":"query-walker-statement-type-mismatch","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}