{"record":{"id":"134cc68ab9dc6a3d","repo":"hibernate/hibernate-orm","slug":"unable-to-interpret-mapping-model-type-for-query-p","errorCode":null,"errorMessage":"Unable to interpret mapping-model type for Query parameter: \" + domainParam","messagePattern":"Unable to interpret mapping-model type for Query parameter: \" \\+ domainParam","errorType":"exception","errorClass":"SqlTreeCreationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java","lineNumber":735,"sourceCode":"\t\t}\n\t\telse if ( domainParamBinding.getBindType() instanceof BasicValuedMapping ) {\n\t\t\treturn ( (BasicValuedMapping) domainParamBinding.getBindType() ).getJdbcMapping();\n\t\t}\n\t\telse {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate static void createValueBindings(\n\t\t\tJdbcParameterBindings jdbcParameterBindings,\n\t\t\tQueryParameterImplementor<?> domainParam,\n\t\t\tQueryParameterBinding<?> domainParamBinding,\n\t\t\tBindable parameterType,\n\t\t\tJdbcParametersList jdbcParams,\n\t\t\tObject bindValue,\n\t\t\tSharedSessionContractImplementor session) {\n\t\tif ( parameterType == null ) {\n\t\t\tthrow new SqlTreeCreationException( \"Unable to interpret mapping-model type for Query parameter: \" + domainParam );\n\t\t}\n\t\tfinal Bindable resolvedParameterType;\n\t\tif ( parameterType instanceof NullType ) {\n\t\t\tassert jdbcParams.size() == 1;\n\t\t\tfinal JdbcMappingContainer expressionType = jdbcParams.get( 0 ).getExpressionType();\n\t\t\tresolvedParameterType = expressionType == null\n\t\t\t\t\t? parameterType\n\t\t\t\t\t// If the parameter bind type is a NullType, which is a BasicValuedMapping,\n\t\t\t\t\t// the JdbcParameters' expression type must be a BasicValuedMapping, which is a Bindable\n\t\t\t\t\t: (Bindable) expressionType;\n\t\t}\n\t\telse {\n\t\t\tresolvedParameterType = parameterType;\n\t\t}\n\t\tfinal int offset =\n\t\t\t\tjdbcParameterBindings.registerParametersForEachJdbcValue(\n\t\t\t\t\t\tbindValue( resolvedParameterType, bindValue, session ),\n\t\t\t\t\t\tparameterType( domainParamBinding, resolvedParameterType ),","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java#L717-L753","documentation":"Thrown as SqlTreeCreationException by SqmUtil.createValueBindings when the mapping-model Bindable type of a query parameter is null, so Hibernate cannot decide how to render and bind the parameter to JDBC. It occurs while translating/binding parameters at query execution: every JDBC parameter must resolve through the domain parameter's Bindable, and a null Bindable means the parameter appeared in a position where Hibernate could not infer a type and no explicit type was given.","triggerScenarios":"Parameters used in positions without type inference: 'where :p is null' (parameter not compared to any typed path), 'where :p1 = :p2' (parameter compared only to another parameter), binding null via setParameter without explicit type information; queries assembled dynamically where the optional-filter parameter keeps appearing after the anchoring predicate was removed.","commonSituations":"Optional-filter patterns like '(:name is null or p.name = :name)' written with the bare ':name is null' branch on databases/Hibernate versions where inference fails; dynamic query builders that keep parameters after dropping their typed anchor predicate; upgrading between Hibernate 6.x versions where parameter type inference rules changed.","solutions":["Anchor the parameter to a typed path: 'where p.name = :p' gives Hibernate the type to infer","Bind with an explicit type: query.setParameter(\"p\", value, StringJavaType.INSTANCE) or the (name, value, Type) overload","Cast the parameter in the query: 'where cast(:p as string) is null'","Build the predicate dynamically and omit the parameter entirely when the value is null, instead of '(:p is null or ...)'"],"exampleFix":"// before\nString hql = \"from Person p where :p is null\";\nList<Person> r = session.createQuery(hql, Person.class).setParameter(\"p\", maybeName).getResultList();\n// after\nString hql = \"from Person p where p.name = :p\";\nList<Person> r = (maybeName == null)\n        ? session.createQuery(\"from Person p\", Person.class).getResultList()\n        : session.createQuery(hql, Person.class).setParameter(\"p\", maybeName, String.class).getResultList();","handlingStrategy":"validation","validationCode":"static String optionalNameFilter(String hql, String paramName, String value) {\n    // omit the parameter entirely when it has no typed anchor\n    if (value == null) {\n        return hql;\n    }\n    return hql + \" and p.name = :\" + paramName;\n}\n\n// when a bare parameter position is unavoidable, bind with an explicit type:\n// query.setParameter(\"p\", value, String.class);","typeGuard":null,"tryCatchPattern":"try {\n    return session.createQuery(hql, Person.class).setParameter(\"p\", value, String.class).getResultList();\n} catch (SqlTreeCreationException e) {\n    // parameter type could not be resolved: log which parameter and rethrow as query config error\n    throw new IllegalStateException(\"Query parameter without resolvable type in: \" + hql, e);\n}","preventionTips":["Never leave a parameter in a position where it is not compared to a typed path","Prefer building predicates dynamically over '(:p is null or ...)' patterns","Always use the typed setParameter(name, value, type) overload for nullable or ambiguous binds","Cast bare parameters: cast(:p as string)"],"tags":["hibernate","query-parameter","binding","type-inference","jdbc"],"backgroundTag":"unresolvable-query-parameter-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}