{"record":{"id":"7a1a6d9dbd3313fc","repo":"hibernate/hibernate-orm","slug":"jdbc-parameter-value-not-bound-s","errorCode":null,"errorMessage":"JDBC parameter value not bound - %s","messagePattern":"JDBC parameter value not bound - (.+?)","errorType":"exception","errorClass":"ExecutionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java","lineNumber":86,"sourceCode":"\tpublic void accept(SqlAstWalker sqlTreeWalker) {\n\t\tsqlTreeWalker.visitParameter( this );\n\t}\n\n\t@Override\n\tpublic JdbcMapping getSingleJdbcMapping() {\n\t\treturn jdbcMapping;\n\t}\n\n\n\t@Override\n\tpublic void bindParameterValue(\n\t\t\tPreparedStatement statement,\n\t\t\tint startPosition,\n\t\t\tJdbcParameterBindings jdbcParamBindings,\n\t\t\tExecutionContext executionContext) throws SQLException {\n\t\tfinal var binding = jdbcParamBindings.getBinding( AbstractJdbcParameter.this );\n\t\tif ( binding == null ) {\n\t\t\tthrow new ExecutionException( \"JDBC parameter value not bound - \" + this );\n\t\t}\n\n\t\tfinal var jdbcMapping = jdbcMapping( executionContext, binding );\n\t\tbindParameterValue( jdbcMapping, statement, binding.getBindValue(), startPosition, executionContext );\n\t}\n\n\tprivate JdbcMapping jdbcMapping(ExecutionContext executionContext, JdbcParameterBinding binding) {\n\t\tJdbcMapping jdbcMapping = binding.getBindType();\n\n\t\tif ( jdbcMapping == null ) {\n\t\t\tjdbcMapping = this.jdbcMapping;\n\t\t}\n\n\t\t// If the parameter type is not known from the context i.e. null or Object, infer it from the bind value\n\t\tif ( jdbcMapping == null || jdbcMapping.getMappedJavaType().getJavaTypeClass() == Object.class ) {\n\t\t\tjdbcMapping = guessBindType( executionContext, binding.getBindValue(), jdbcMapping );\n\t\t}\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java#L68-L104","documentation":"When binding a PreparedStatement, Hibernate looks up the JdbcParameterBinding for each JdbcParameter in JdbcParameterBindings. If no binding was collected for that parameter instance during query translation/execution preparation, bindParameterValue throws ExecutionException('JDBC parameter value not bound - ' + parameter). The SQL contains a '?' whose parameter object has no entry in the binding map - a translation/binding pipeline mismatch, not a value the user forgot to set.","triggerScenarios":"Executing a query whose SQL AST was built with JdbcParameter instances that never got registered in JdbcParameterBindingsImpl - typical of custom SqlAstTranslators, custom functions or dialect extensions that create parameters during rendering but skip binding registration; also cached query plans executed with bindings prepared against a different plan.","commonSituations":"Upgrading Hibernate with a stale query plan cache; custom dialect/function code creating parameters on one path and binding on another; concurrency bugs that reuse query plans across mismatched translations. When hit with vanilla mappings this message usually marks a Hibernate bug.","solutions":["If a custom function/dialect creates JdbcParameters, register matching JdbcParameterBindings during rendering (mirror how standard functions do it)","Clear or size down the query plan cache (hibernate.query.plan_cache_max_size, or restart) after upgrading Hibernate or swapping dialects to rule out stale plans","Reproduce with a minimal entity/query and check/report the Hibernate JIRA (HHH) - this message typically indicates an internal bug","As a workaround, disable the plan cache (hibernate.query.plan_cache_max_size=0) to force retranslation per execution"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return query.list();\n} catch ( ExecutionException e ) {\n    if ( e.getMessage() != null && e.getMessage().startsWith( \"JDBC parameter value not bound\" ) ) {\n        // translation/binding mismatch: force retranslation, then retry once\n        session.getFactory().getQueryPlanCache().clear();\n        return session.createQuery( query.getQueryString(), query.getResultType() ).list();\n    }\n    throw e;\n}","preventionTips":["Register JdbcParameterBindings for every JdbcParameter your custom function/translator creates","Clear or size the query plan cache after upgrading Hibernate or changing dialects","Report pure-mapping occurrences to the Hibernate JIRA (HHH) with a minimal reproducer"],"tags":["hibernate","orm","jdbc","parameter-binding","query-execution"],"backgroundTag":"unbound-jdbc-parameter","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}