hibernate/hibernate-orm · error · QueryException

Emulation of function chr() supports only integer literals,

Error message

Emulation of function chr() supports only integer literals, but %s argument given

What it means

ChrLiteralEmulation is registered by dialects that lack a native chr() function; it rewrites chr(<int literal>) into a char literal during query compilation. Because the rewrite needs the actual integer at compile time, passing anything that is not an SqmLiteral (parameter, column, expression) throws a QueryException naming the argument's class name.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/ChrLiteralEmulation.java:48

/**
 * A chr implementation that translates integer literals to string literals.
 *
 * @author Christian Beikov
 */
public class ChrLiteralEmulation extends AbstractSqmSelfRenderingFunctionDescriptor {

	public ChrLiteralEmulation(TypeConfiguration typeConfiguration) {
		super(
				"chr",
				new ArgumentTypesValidator(
						StandardArgumentsValidators.composite(
								StandardArgumentsValidators.exactly(1),
								new ArgumentsValidator() {
									@Override
									public void validate(List<? extends SqmTypedNode<?>> arguments, String functionName, BindingContext bindingContext) {
										final var arg = arguments.get( 0 );
										if ( !( arg instanceof SqmLiteral<?> ) ) {
											throw new QueryException(
													String.format(
															Locale.ROOT,
															"Emulation of function chr() supports only integer literals, but %s argument given",
															arg.getClass().getName()
													)
											);
										}
									}
								}
						),
						INTEGER
				),
				StandardFunctionReturnTypeResolvers.invariant(
						typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.CHARACTER )
				),
				StandardFunctionArgumentTypeResolvers.invariant( typeConfiguration, INTEGER )
		);
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass a constant integer literal: chr(65), or precompute the character in Java and use a plain char/String parameter
  2. Replace chr() with the equivalent HQL/JPQL: use a bind parameter of type Character/String instead of building characters in SQL
  3. If you need runtime chr(), override the dialect function with a native or SQL-based implementation (e.g. char() on MySQL/SAP HANA) that accepts expressions

Example fix

// before
session.createQuery("from Code c where c.ch = chr(:n)").setParameter("n", 65);

// after
session.createQuery("from Code c where c.ch = :ch").setParameter("ch", 'A'); // resolved in Java
Defensive patterns

Strategy: type-guard

Type guard

// In Java: guard that chr() only ever receives compile-time constants
boolean chrSafe(Object arg) { return arg instanceof Integer i && isQueryLiteral(i); }

Try / catch

catch (QueryException e) {
    if (e.getMessage().contains("chr()")) {
        // fall back to binding the character as a parameter
        return session.createQuery("from Code c where c.ch = :ch", Code.class)
                      .setParameter("ch", (char) code);
    }
    throw e;
}

Prevention

When it happens

Trigger: Using chr() on a dialect that registers the emulation with a non-literal argument: 'from E where e.code = chr(:code)', chr(e.col), chr(65+1), or criteria builder chr( parameter ). Only a constant like chr(65) is accepted.

Common situations: Porting queries from PostgreSQL/Oracle (native chr) to a database whose dialect emulates chr; dynamic queries building chr() around user input parameters; test code running against H2/other DB whose dialect chain enables the emulation.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/14e61441a951a214. Report an issue: GitHub.