{"record":{"id":"39c4520a0903cb8b","repo":"hibernate/hibernate-orm","slug":"function-s-requires-between-d-and-d-arguments","errorCode":null,"errorMessage":"Function %s() requires between %d and %d arguments, but %d arguments given","messagePattern":"Function (.+?)\\(\\) requires between (.+?) and (.+?) arguments, but (.+?) arguments given","errorType":"exception","errorClass":"FunctionArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java","lineNumber":191,"sourceCode":"\t\t\t\t\t\tsig.append(\", \");\n\t\t\t\t\t}\n\t\t\t\t\tsig.append(\"arg\").append(i);\n\t\t\t\t}\n\t\t\t\tsig.append(\"])\");\n\t\t\t\treturn sig.toString();\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic static ArgumentsValidator between(int minNumOfArgs, int maxNumOfArgs) {\n\t\treturn new ArgumentsValidator() {\n\t\t\t@Override\n\t\t\tpublic void validate(\n\t\t\t\t\tList<? extends SqmTypedNode<?>> arguments,\n\t\t\t\t\tString functionName,\n\t\t\t\t\tBindingContext bindingContext) {\n\t\t\t\tif ( arguments.size() < minNumOfArgs || arguments.size() > maxNumOfArgs ) {\n\t\t\t\t\tthrow new FunctionArgumentException(\n\t\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\t\t\"Function %s() requires between %d and %d arguments, but %d arguments given\",\n\t\t\t\t\t\t\t\t\tfunctionName,\n\t\t\t\t\t\t\t\t\tminNumOfArgs,\n\t\t\t\t\t\t\t\t\tmaxNumOfArgs,\n\t\t\t\t\t\t\t\t\targuments.size()\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getSignature() {\n\t\t\t\tfinal var sig = new StringBuilder(\"(\");\n\t\t\t\tfor (int i=0; i<maxNumOfArgs; i++) {\n\t\t\t\t\tif (i==minNumOfArgs) {\n\t\t\t\t\t\tsig.append(\"[\");","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardArgumentsValidators.java#L173-L209","documentation":"Hibernate 6 validates every HQL/criteria function call while the query is parsed. StandardArgumentsValidators.between(minNumOfArgs, maxNumOfArgs) creates the validator used by most registered SqmFunctionDescriptors, and it throws this FunctionArgumentException as soon as the parsed argument list falls outside [min, max]. The query never reaches SQL generation; the failure surfaces from EntityManager.createQuery(...) or the criteria compile step.","triggerScenarios":"Calling an HQL function with the wrong arity, e.g. substring(p.name) (requires 2-3), locate(p.name) (requires 2-3), or a custom function registered with between(1,2) but invoked with 3 arguments: select my_func(a, b, c). The validator runs at query creation time, not at execution.","commonSituations":"Hand-written HQL with a typo'd argument list; signatures tightened during Hibernate 5.x to 6.x migration so previously tolerated calls now fail; a dialect or FunctionContributor registering a descriptor with wrong between() bounds; pasting native SQL with optional arguments into HQL.","solutions":["Fix the HQL call to pass the number of arguments the function declares - the message states the accepted min/max and the count actually passed.","If the function is your own (dialect/FunctionContributor), correct the between(min,max) bounds or use Parameters.variadic(...) for genuinely optional or repeating arguments.","If the function is native to your database only, register a proper descriptor or call it through native SQL instead of HQL.","Inspect the function in force via QueryEngine.getSqmFunctionRegistry() to confirm the arity of your Hibernate version."],"exampleFix":"// before - substring requires 2 or 3 arguments\nselect p from Person p where substring(p.name) = 'x'\n\n// after\nselect p from Person p where substring(p.name, 1, 4) = 'x'","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    TypedQuery<Person> q = em.createQuery(hql, Person.class);\n} catch (org.hibernate.query.sqm.produce.function.FunctionArgumentException e) {\n    // parse-time failure; the message states function name, min/max arity, and actual count\n    throw new BadRequestException(\"Invalid function call: \" + e.getMessage(), e);\n}","preventionTips":["Unit-test every custom HQL string against the exact Hibernate version you ship; arity enforcement differs across versions.","Keep custom function registrations (dialect/FunctionContributor) under integration test covering both min and max arity.","Log the offending HQL whenever this exception fires so the call site is identifiable in production."],"tags":["hibernate","hql","sqm","function","arity","query-parsing"],"backgroundTag":"function-argument-count-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}