{"record":{"id":"32dfac48829daa0a","repo":"hibernate/hibernate-orm","slug":"expecting-a-select-query-s-but-found-s","errorCode":null,"errorMessage":"Expecting a SELECT Query [%s], but found %s","messagePattern":"Expecting a SELECT Query \\[(.+?)\\], but found (.+?)","errorType":"exception","errorClass":"IllegalSelectQueryException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java","lineNumber":147,"sourceCode":"\tpublic static boolean isSelect(SqmStatement<?> sqm) {\n\t\treturn sqm instanceof SqmSelectStatement;\n\t}\n\n\tpublic static boolean isMutation(SqmStatement<?> sqm) {\n\t\treturn sqm instanceof SqmDmlStatement;\n\t}\n\n\tpublic static <T> boolean isRestrictedMutation(SqmStatement<T> sqmStatement) {\n\t\treturn sqmStatement instanceof SqmDeleteOrUpdateStatement;\n\t}\n\n\tpublic static <R> SqmSelectStatement<R> asSelectStatement(SqmStatement<?> sqm, String hqlString) {\n\t\tif ( sqm instanceof SqmSelectStatement<?> selectAst ) {\n\t\t\t//noinspection unchecked\n\t\t\treturn (SqmSelectStatement<R>) selectAst;\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalSelectQueryException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\"Expecting a SELECT Query [%s], but found %s\",\n\t\t\t\t\t\t\tSqmSelectStatement.class.getName(),\n\t\t\t\t\t\t\tsqm.getClass().getName()\n\t\t\t\t\t),\n\t\t\t\t\thqlString\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic static void verifyIsSelectStatement(SqmStatement<?> sqm, String hqlString) {\n\t\tif ( ! isSelect( sqm ) ) {\n\t\t\tthrow new IllegalSelectQueryException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\"Expecting a SELECT Query [%s], but found %s\",\n\t\t\t\t\t\t\tSqmSelectStatement.class.getName(),","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java#L129-L165","documentation":"SqmUtil.asSelectStatement is the choke point where Hibernate asserts that an SQM statement it is about to treat as a query (typed results, scrolling, paging) really is an SqmSelectStatement. Passing an update/delete/insert statement — usually because HQL text like 'update ...' was handed to a select-oriented API — throws IllegalSelectQueryException with both class names in the message.","triggerScenarios":"em.createQuery(hql, Order.class) where hql = 'update Order o set ...' (typed query creation implies select); session.createQuery(hql).getSingleResult() / setMaxResults / scroll on mutation HQL; feeding a mutation query through APIs like SQM copying or name-based typed lookups that internally call asSelectStatement.","commonSituations":"Concatenated/templated HQL that flips between select and bulk statements; DML statements routed to createQuery instead of createMutationQuery during refactors; migration from Hibernate 5 where some leniency existed; GUI query builders executing user-entered HQL.","solutions":["Use the mutation API for non-select HQL: em.createMutationQuery(hql).executeUpdate() (Hibernate 6+) / session.createMutationQuery(...).","If the statement should be a select, fix the HQL itself (missing 'select'/'from' clause, wrong keyword, truncated string).","Branch on the first keyword of dynamic HQL before choosing createQuery vs createMutationQuery."],"exampleFix":"// before\nQuery<Order> q = em.createQuery(\"update Order o set o.status = :s\", Order.class);\nq.getResultList(); // Expecting a SELECT Query [...], but found SqmUpdateStatement\n\n// after\nMutationQuery q = em.createMutationQuery(\"update Order o set o.status = :s\").setParameter(\"s\", \"OPEN\");\nq.executeUpdate();","handlingStrategy":"validation","validationCode":"static boolean isSelectHql(String hql) {\n    String head = hql.trim().toLowerCase(Locale.ROOT);\n    return head.startsWith(\"select\") || head.startsWith(\"from\");\n}\nif (!isSelectHql(hql)) throw new IllegalArgumentException(\"use createMutationQuery for: \" + hql);","typeGuard":"static boolean isMutationHql(String hql) {\n    String head = hql.trim().toLowerCase(Locale.ROOT);\n    return head.startsWith(\"update\") || head.startsWith(\"delete\") || head.startsWith(\"insert\");\n}","tryCatchPattern":"try {\n    results = em.createQuery(hql, type).getResultList();\n} catch (IllegalSelectQueryException e) {\n    // HQL was update/delete/insert: route to the mutation API instead\n    em.createMutationQuery(hql).executeUpdate();\n}","preventionTips":["Route by statement type at one choke point: select/from -> createQuery, update/delete/insert -> createMutationQuery.","Never pass user-supplied HQL straight into a typed createQuery without a keyword check.","Prefer the criteria API for dynamic statements so the compiler fixes the statement type."],"tags":["hibernate","hql","query","select-statement","mutation-query"],"backgroundTag":"hql-query-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}