{"record":{"id":"cdbb3f63eb8c8c26","repo":"hibernate/hibernate-orm","slug":"type-specified-for-parameter-at-position-position","errorCode":null,"errorMessage":"Type specified for parameter at position {position} is incompatible ({parameterType.getName()} is not assignable to {type.getName()})","messagePattern":"Type specified for parameter at position (.+?) 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":912,"sourceCode":"\tpublic QueryParameterImplementor<?> getParameter(int position) {\n\t\tsession.checkOpen( false );\n\t\ttry {\n\t\t\treturn getParameterMetadata().getQueryParameter( position );\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(int position, @Nonnull Class<T> type) {\n\t\tsession.checkOpen( false );\n\t\ttry {\n\t\t\tfinal var parameter = getParameterMetadata().getQueryParameter( position );\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 at position \" + position + \" 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\tpublic <T> T getParameterValue(@Nonnull Parameter<T> param) {\n\t\tsession.checkOpen( false );\n\t\tfinal var parameter = getParameterMetadata().resolve( param );\n\t\tif ( parameter == null ) {","sourceCodeStart":894,"sourceCodeEnd":930,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java#L894-L930","documentation":"Positional twin of error 2368: getParameter(int position, Class<T> type) looks up the ordinal parameter via getParameterMetadata().getQueryParameter(position) and rejects the request when !type.isAssignableFrom(parameterType). The parameter's determined type (from query analysis) must be the requested type or a subtype; otherwise IllegalArgumentException with both class names is thrown before any result execution.","triggerScenarios":"query.getParameter(1, Integer.class) where parameter ?1 is bound/inferred as Long, LocalDate, or an enum. Reusing a typed accessor across queries whose positional parameters have different inferred types (native queries often infer differently than HQL). Generic repositories calling getParameter(position, expectedClass) from a per-entity type registry.","commonSituations":"Native queries where parameter types come from result-set mapping or are Object until bound; Java 8 Date vs java.time migrations; upgrading Hibernate and getting stricter/different parameter type inference.","solutions":["Check the actual type with getParameterMetadata().getQueryParameter(position).getParameterType() and request exactly that","Request a supertype (Number/Object) when you only read the value","For native queries, set the type explicitly at bind time: query.setParameter(1, value, Long.class), which also fixes later getParameter calls","Align the expected type in helper code with the query's real inference (sum→Long etc.)"],"exampleFix":"// before\nQueryParameterImplementor<Integer> p = query.getParameter( 1, Integer.class );\n// Long/LocalDate etc. not assignable to Integer\n\n// after\nQueryParameterImplementor<Long> p = query.getParameter( 1, Long.class );","handlingStrategy":"validation","validationCode":"Class<?> actual = query.getParameterMetadata().getQueryParameter( position ).getParameterType();\nif ( !expected.isAssignableFrom( actual ) ) throw new IllegalStateException( \"Param \" + position + \" is \" + actual + \", not \" + expected );\nQueryParameterImplementor<T> p = query.getParameter( position, expected );","typeGuard":"static <T> boolean parameterTypeMatches(\n        org.hibernate.query.Query<?> q, int position, Class<T> expected) {\n    Class<?> actual = q.getParameterMetadata().getQueryParameter( position ).getParameterType();\n    return expected.isAssignableFrom( actual );\n}","tryCatchPattern":null,"preventionTips":["For native queries, always bind with an explicit type: query.setParameter(1, v, Long.class)","Don't hardcode Integer/Date in generic accessors; derive from metadata","Test typed accessors whenever the query string or mapping changes"],"tags":["hibernate","query-parameters","positional-parameters","type-mismatch","illegalargument"],"backgroundTag":"query-parameter-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}