{"record":{"id":"0e558d1859f6377e","repo":"hibernate/hibernate-orm","slug":"can-t-render-parameter-as-literal-no-literal-form","errorCode":null,"errorMessage":"Can't render parameter as literal, no literal formatter found","messagePattern":"Can't render parameter as literal, no literal formatter found","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java","lineNumber":7656,"sourceCode":"\t\tif ( getParameterRenderingMode() == SqlAstNodeRenderingMode.NO_UNTYPED ) {\n\t\t\trenderCasted( literal );\n\t\t}\n\t\telse {\n\t\t\tappendSql( SqlAppender.NULL_KEYWORD );\n\t\t}\n\t}\n\n\tprotected void renderAsLiteral(JdbcParameter jdbcParameter, Object literalValue) {\n\t\tif ( literalValue == null ) {\n\t\t\trenderNull( new QueryLiteral<>( null, (BasicValuedMapping) jdbcParameter.getExpressionType() ) );\n\t\t}\n\t\telse {\n\t\t\tassert jdbcParameter.getExpressionType().getJdbcTypeCount() == 1;\n\t\t\tfinal JdbcMapping jdbcMapping = jdbcParameter.getExpressionType().getSingleJdbcMapping();\n\t\t\t//noinspection unchecked\n\t\t\tfinal JdbcLiteralFormatter<Object> literalFormatter = jdbcMapping.getJdbcLiteralFormatter();\n\t\t\tif ( literalFormatter == null ) {\n\t\t\t\tthrow new IllegalArgumentException( \"Can't render parameter as literal, no literal formatter found\" );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tliteralFormatter.appendJdbcLiteral( this, literalValue, dialect, getWrapperOptions() );\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression) {\n\t\tif ( unaryOperationExpression.getOperator() == UnaryArithmeticOperator.UNARY_PLUS ) {\n\t\t\tappendSql( UnaryArithmeticOperator.UNARY_PLUS.getOperatorChar() );\n\t\t}\n\t\telse {\n\t\t\tappendSql( UnaryArithmeticOperator.UNARY_MINUS.getOperatorChar() );\n\t\t}\n\n\t\tunaryOperationExpression.getOperand().accept( this );\n\t}","sourceCodeStart":7638,"sourceCodeEnd":7674,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java#L7638-L7674","documentation":"In certain SQL positions Hibernate must render a JDBC parameter inline as a literal (e.g. limit/offset values on dialects that cannot bind parameters there, or inlined static parameters). renderAsLiteral asks the parameter's JdbcMapping for a JdbcLiteralFormatter; if the mapping provides none (common for exotic/basic-java-type mappings), rendering is impossible and this IllegalArgumentException is thrown.","triggerScenarios":"A query whose parameter must be rendered literally (dialect-specific limit emulation, in-clause parameter inlining, or explicit literal rendering mode) where the bound parameter's type has getJdbcLiteralFormatter() == null - e.g. custom BasicType/JavaType without a literal formatter, or certain binary/java-object mappings.","commonSituations":"Custom UserTypes/BasicTypes that implement the binder but not the literal formatter; pagination on dialects that inline the fetch value; switching a parameter's Java type to one lacking formatter support; Hibernate 6 migration where literal rendering paths expanded.","solutions":["Use a standard Java/JDBC type for the parameter (Integer, String, LocalDate...) that has a built-in formatter","For custom types, register a BasicType/JavaType that supplies a JdbcLiteralFormatter","Avoid the construct that forces literal rendering (e.g. use setMaxResults so the dialect takes the native parameter path)","Upgrade Hibernate - formatter coverage for more JDBC types improves by version"],"exampleFix":"// before\ncustom BasicType without literal formatter used where dialect inlines parameters\n\n// after\n// register the type with a formatter\nBasicType<MyType> t = new MyTypeRenderer(new MyTypeJavaType() {\n    @Override public JdbcLiteralFormatter<MyType> getJdbcLiteralFormatter() { return (appender, value, dialect, wrapper) -> appender.appendSql(value.render()); }\n});","handlingStrategy":"fallback","validationCode":"// Before executing with inlined parameters, confirm the mapping can render literals\nJdbcMapping m = (JdbcMapping) param.getExpressionType().getSingleJdbcMapping();\nif (m.getJdbcLiteralFormatter() == null) {\n    // switch the parameter to a standard type or avoid the literal-rendering construct\n}","typeGuard":null,"tryCatchPattern":"try {\n    query.list();\n} catch (IllegalArgumentException e) {\n    if (\"Can't render parameter as literal, no literal formatter found\".equals(e.getMessage())) {\n        // rebind the parameter with a standard Java type and retry\n    } else throw e;\n}","preventionTips":["Bind parameters as standard Java types (Integer, String, LocalDate...)","For custom types, always provide a JdbcLiteralFormatter in the JavaType/BasicType","Prefer setMaxResults/setFirstResult over constructs that force literal rendering"],"tags":["hibernate","parameter-inlining","jdbc-literal-formatter","custom-type","sql-translator"],"backgroundTag":"parameter-literal-inlining","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}