{"record":{"id":"82970b30183e52b3","repo":"doctrine/orm","slug":"the-hint-hint-cache-evict-is-not-valid-for-selec","errorCode":null,"errorMessage":"The hint \"HINT_CACHE_EVICT\" is not valid for select statements.","messagePattern":"The hint \"HINT_CACHE_EVICT\" is not valid for select statements\\.","errorType":"exception","errorClass":"QueryException","httpStatus":null,"severity":"error","filePath":"src/Query.php","lineNumber":334,"sourceCode":"        assert($cache !== null);\n\n        $statements = (array) $executor->getSqlStatements(); // Type casted since it can either be a string or an array\n\n        foreach ($statements as $statement) {\n            $cacheKeys = $this->queryCacheProfile->generateCacheKeys($statement, $sqlParams, $types, $connectionParams);\n            $cache->deleteItem(reset($cacheKeys));\n        }\n    }\n\n    /**\n     * Evict entity cache region\n     */\n    private function evictEntityCacheRegion(): void\n    {\n        $AST = $this->getAST();\n\n        if ($AST instanceof SelectStatement) {\n            throw new QueryException('The hint \"HINT_CACHE_EVICT\" is not valid for select statements.');\n        }\n\n        $className = $AST instanceof DeleteStatement\n            ? $AST->deleteClause->abstractSchemaName\n            : $AST->updateClause->abstractSchemaName;\n\n        $this->em->getCache()->evictEntityRegion($className);\n    }\n\n    /**\n     * Processes query parameter mappings.\n     *\n     * @param array<list<int>> $paramMappings\n     *\n     * @return mixed[][]\n     * @phpstan-return array{0: list<mixed>, 1: array}\n     *\n     * @throws Query\\QueryException","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Query.php#L316-L352","documentation":"Query::HINT_CACHE_EVICT instructs the ORM to evict the second-level-cache entity region affected by a DQL statement. It only makes sense for UPDATE/DELETE: during execute(), evictEntityCacheRegion() inspects the AST and throws a QueryException if the statement is a SelectStatement, because a SELECT has no affected entity region to evict.","triggerScenarios":"$query->setHint(Query::HINT_CACHE_EVICT, true) followed by executing a SELECT DQL query while second-level cache is enabled (hasCache) — the check runs in _doExecute() before parameter processing.","commonSituations":"Copy-pasting a cache-eviction hint between queries; applying the hint to a query builder that later becomes a select; blindly enabling all cache hints when turning on the second-level cache.","solutions":["Remove the HINT_CACHE_EVICT hint from SELECT queries — set it only on UPDATE/DELETE DQL","To invalidate cached query/entity data after a select-driven change, evict explicitly: $em->getCache()->evictEntityRegion(Entity::class) or ->evictEntity(Entity::class, $id)","Keep hint-setting conditional on the statement type when hints are configured centrally"],"exampleFix":"// before\n$q = $em->createQuery('SELECT u FROM App\\Entity\\User u WHERE u.id = :id');\n$q->setHint(Query::HINT_CACHE_EVICT, true); // throws on execute\n\n// after\n$q = $em->createQuery('SELECT u FROM App\\Entity\\User u WHERE u.id = :id');\n// evict manually if needed:\n$em->getCache()->evictEntity(User::class, $id);","handlingStrategy":"validation","validationCode":"// Only set the hint on UPDATE/DELETE DQL\nif (in_array($queryType, ['update', 'delete'], true)) {\n    $query->setHint(Query::HINT_CACHE_EVICT, true);\n}","typeGuard":null,"tryCatchPattern":"try { $result = $query->execute(); } catch (QueryException $e) { if (str_contains($e->getMessage(), 'HINT_CACHE_EVICT')) { $query->setHint(Query::HINT_CACHE_EVICT, false); $result = $query->execute(); } else { throw $e; } }","preventionTips":["Set HINT_CACHE_EVICT only on UPDATE/DELETE statements","Centralize hint configuration and gate it by statement type","Prefer explicit $em->getCache()->evictEntityRegion() for invalidation"],"tags":["second-level-cache","query-hints","dql","cache-eviction"],"backgroundTag":"invalid-query-hint","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}