{"record":{"id":"4b2aa9cc700a0618","repo":"hibernate/hibernate-orm","slug":"incorrect-query-result-type-query-produces-s-b","errorCode":null,"errorMessage":"Incorrect query result type: query produces '%s' but type '%s' was given","messagePattern":"Incorrect query result type: query produces '(.+?)' but type '(.+?)' was given","errorType":"exception","errorClass":"QueryTypeMismatchException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java","lineNumber":2082,"sourceCode":"\n\tprotected HqlInterpretation<?> interpretHql(String hql) {\n\t\treturn interpretHql( hql, null );\n\t}\n\n\tprotected <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {\n\t\treturn getFactory().getQueryEngine().interpretHql( hql, resultType );\n\t}\n\n\tprotected static void checkSelectionQuery(String hql, HqlInterpretation<?> hqlInterpretation) {\n\t\tif ( !( hqlInterpretation.getSqmStatement() instanceof SqmSelectStatement ) ) {\n\t\t\tthrow new IllegalSelectQueryException( \"Expecting a selection query, but found '\" + hql + \"'\", hql);\n\t\t}\n\t}\n\n\tprotected static <R> void checkResultType(Class<R> expectedResultType, SelectionQuery<R> query) {\n\t\tfinal var resultType = query.getResultType();\n\t\tif ( !expectedResultType.isAssignableFrom( resultType ) ) {\n\t\t\tthrow new QueryTypeMismatchException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\"Incorrect query result type: query produces '%s' but type '%s' was given\",\n\t\t\t\t\t\t\texpectedResultType.getName(),\n\t\t\t\t\t\t\tresultType.getName()\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected NamedResultSetMappingMemento getResultSetMappingMemento(String resultSetMappingName) {\n\t\tfinal var resultSetMappingMemento =\n\t\t\t\tnamedObjectRepository().getResultSetMappingMemento( resultSetMappingName );\n\t\tif ( resultSetMappingMemento == null ) {\n\t\t\tthrow new HibernateException( \"No result set mapping with given name '\" + resultSetMappingName + \"'\" );\n\t\t}\n\t\treturn resultSetMappingMemento;\n\t}","sourceCodeStart":2064,"sourceCodeEnd":2100,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java#L2064-L2100","documentation":"Typed query creation (createSelectionQuery/createQuery with an expected result class) calls checkResultType(): the query's actual result type must be assignable to the requested class, otherwise QueryTypeMismatchException('Incorrect query result type: query produces X but type Y was given'). It enforces the contract between the HQL select list and the Java type before execution.","triggerScenarios":"createQuery(\"select count(u) from User u\", Integer.class) when count() produces Long; a projection (select new Dto(...)/multi-column) queried with the entity class; expecting a scalar when the select list yields Object[]; DTO constructor signature not matching columns.","commonSituations":"count queries typed as Integer/int from pre-JPA ports or naive refactors; switching between entity and DTO selects without updating the class argument; multi-select expected as scalar; Java primitives boxed to the wrong wrapper type.","solutions":["Match the class to the select list: counts are Long.class; multi-column selects need Object[]/Tuple/the exact DTO class.","Adjust the HQL select clause to produce the requested shape (e.g., select new com.Dto(a.id, a.name)).","Create the query untyped and map results manually when shapes vary at runtime."],"exampleFix":"// before\nLong n = session.createQuery(\"select count(u) from User u\", Integer.class).getSingleResult();\n// QueryTypeMismatchException: query produces java.lang.Long\n// after\nLong n = session.createQuery(\"select count(u) from User u\", Long.class).getSingleResult();","handlingStrategy":"validation","validationCode":"// Create untyped first, inspect the real result type, then act\nSelectionQuery<?> raw = session.createSelectionQuery(hql);\nClass<?> actual = raw.getResultType();\nif (!expectedType.isAssignableFrom(actual)) {\n    throw new IllegalArgumentException(\n        \"HQL produces \" + actual.getName() + \"; caller expected \" + expectedType.getName());\n}\n@SuppressWarnings(\"unchecked\")\nSelectionQuery<T> typed = (SelectionQuery<T>) raw;","typeGuard":null,"tryCatchPattern":"try {\n    return session.createSelectionQuery(hql, expectedType).list();\n} catch (QueryTypeMismatchException e) {\n    // dynamic HQL: fall back to untyped query with manual mapping\n    return mapManually(session.createSelectionQuery(hql).list());\n}","preventionTips":["Type count queries as Long.class, never Integer/int","Write the select list and the result class argument together, as one unit, in reviews","Use Tuple or Object[] for multi-selects instead of guessing a scalar type"],"tags":["hibernate","hql","type-mismatch","query","result-type"],"backgroundTag":"query-result-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}