{"record":{"id":"96ad0ea1d793d627","repo":"hibernate/hibernate-orm","slug":"type-specified-for-parameter-named-name-is-inc","errorCode":null,"errorMessage":"Type specified for parameter named '{name}' is incompatible ({parameterType.getName()} is not assignable to {type.getName()})","messagePattern":"Type specified for parameter named '(.+?)' is incompatible \\((.+?) is not assignable to (.+?)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java","lineNumber":878,"sourceCode":"\tpublic QueryParameterImplementor<?> getParameter(@Nonnull String name) {\n\t\tsession.checkOpen( false );\n\t\ttry {\n\t\t\treturn getParameterMetadata().getQueryParameter( name );\n\t\t}\n\t\tcatch ( HibernateException e ) {\n\t\t\tthrow getExceptionConverter().convert( e );\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <T> QueryParameterImplementor<T> getParameter(@Nonnull String name, @Nonnull Class<T> type) {\n\t\tsession.checkOpen( false );\n\t\ttry {\n\t\t\tfinal var parameter = getParameterMetadata().getQueryParameter( name );\n\t\t\tfinal var parameterType = parameter.getParameterType();\n\t\t\tif ( !type.isAssignableFrom( parameterType ) ) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Type specified for parameter named '\" + name + \"' is incompatible\"\n\t\t\t\t\t\t+ \" (\" + parameterType.getName() + \" is not assignable to \" + type.getName() + \")\"\n\t\t\t\t);\n\t\t\t}\n\t\t\t@SuppressWarnings(\"unchecked\") // safe, just checked\n\t\t\tvar castParameter = (QueryParameterImplementor<T>) parameter;\n\t\t\treturn castParameter;\n\t\t}\n\t\tcatch ( HibernateException e ) {\n\t\t\tthrow getExceptionConverter().convert( e );\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic QueryParameterImplementor<?> getParameter(int position) {\n\t\tsession.checkOpen( false );\n\t\ttry {","sourceCodeStart":860,"sourceCodeEnd":896,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java#L860-L896","documentation":"Thrown by getParameter(String name, Class<T> type) when the requested type is not a supertype of the parameter's determined type: the check is !type.isAssignableFrom(parameter.getParameterType()), so the parameter's runtime Java type must be assignable TO the class you request. The message prints both class names (actual first, requested second). A HibernateException raised inside is converted by the exception converter, but this incompatibility is a raw IllegalArgumentException.","triggerScenarios":"query.getParameter(\"total\", Integer.class) where the HQL 'select sum(o.price)' inferred the parameter/expression type as Long — Long is not assignable to Integer, so it fails. Requesting java.util.Date for a parameter bound as java.sql.Timestamp/LocalDate, or String for an enum-typed parameter. Generic helper code doing getParameter(name, expectedType) with a fixed type map.","commonSituations":"HQL function return types (sum → Long/Double/BigInteger depending on operand) after upgrading from Hibernate 5.x where type inference differed; temporal parameter types differing between java.util.Date and java.time types across a migration; helpers written against one schema reused on another.","solutions":["Request the wider type: getParameter(\"total\", Number.class) or the exact inferred type (Long for sum over integral columns, Double for floating point)","Inspect the real type first: getParameterMetadata().getQueryParameter(name).getParameterType() and pass that class","Force the wanted type in HQL: cast(o.price as Integer) or treat the parameter accordingly","Fix caller code that assumed Integer/Date and handle the actual type (e.g. .longValue())"],"exampleFix":"// before\nQueryParameterImplementor<Integer> p = query.getParameter( \"total\", Integer.class );\n// 'java.lang.Long is not assignable to java.lang.Integer'\n\n// after\nQueryParameterImplementor<Long> p = query.getParameter( \"total\", Long.class ); // sum() infers Long","handlingStrategy":"validation","validationCode":"Class<?> actual = query.getParameterMetadata().getQueryParameter( name ).getParameterType();\nif ( !expected.isAssignableFrom( actual ) ) {\n    expected = (Class<T>) actual; // or fail fast with a clear message\n}\nQueryParameterImplementor<T> p = query.getParameter( name, expected );","typeGuard":"static <T> boolean parameterTypeMatches(\n        org.hibernate.query.Query<?> q, String name, Class<T> expected) {\n    Class<?> actual = q.getParameterMetadata().getQueryParameter( name ).getParameterType();\n    return expected.isAssignableFrom( actual );\n}","tryCatchPattern":null,"preventionTips":["Prefer requesting the exact inferred type (sum→Long) or a supertype like Number","Cache the parameter type per query template and reuse it for typed accessors","Cover typed getParameter calls in tests so type-inference changes on upgrade are caught"],"tags":["hibernate","query-parameters","type-mismatch","hql","illegalargument"],"backgroundTag":"query-parameter-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}