{"record":{"id":"af1308a3b1914e6c","repo":"hibernate/hibernate-orm","slug":"missing-parameter-index-in-pattern-pattern","errorCode":null,"errorMessage":"Missing parameter index in pattern: '<pattern>'","messagePattern":"Missing parameter index in pattern: '<pattern>'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/internal/PatternRenderer.java","lineNumber":131,"sourceCode":"\t\tif ( !chunk.isEmpty() ) {\n\t\t\tchunkList.add( chunk.toString() );\n\t\t}\n\n\t\tthis.varargParam = vararg;\n\t\tthis.maxParamIndex = max;\n\n\t\tthis.chunks = chunkList.toArray( EMPTY_STRING_ARRAY );\n\t\tint[] paramIndexes = new int[paramList.size()];\n\t\tfor ( i = 0; i < paramIndexes.length; ++i ) {\n\t\t\tparamIndexes[i] = paramList.get( i );\n\t\t}\n\t\tthis.paramIndexes = paramIndexes;\n\t\tthis.argumentRenderingModes = argumentRenderingModes;\n\t}\n\n\tprivate static int parameterIndex(String pattern, String index) {\n\t\tif ( index.isEmpty() ) {\n\t\t\tthrow new IllegalArgumentException( \"Missing parameter index in pattern: '\" + pattern + \"'\" );\n\t\t}\n\t\tfinal int paramNumber;\n\t\ttry {\n\t\t\tparamNumber = parseInt( index );\n\t\t}\n\t\tcatch (NumberFormatException nfe) {\n\t\t\tthrow new IllegalArgumentException( \"Illegal parameter index '\" + index\n\t\t\t\t\t\t\t\t\t\t\t\t+ \"' in pattern: '\" + pattern + \"'\", nfe );\n\t\t}\n\t\treturn paramNumber;\n\t}\n\n\tpublic boolean hasVarargs() {\n\t\treturn varargParam >= 0;\n\t}\n\n\tpublic int getParamCount() {\n\t\treturn maxParamIndex;","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/internal/PatternRenderer.java#L113-L149","documentation":"PatternRenderer compiles the SQL pattern of a pattern-based function descriptor. Placeholders are written as '?' immediately followed by the 1-based argument number (?1, ?2, ...). parameterIndex throws IllegalArgumentException('Missing parameter index...') when the pattern contains a bare '?' with no digits after it. The exception fires when the renderer is constructed - i.e. at function registration during startup - so the application fails to boot or the dialect fails to initialize.","triggerScenarios":"Registering a function whose SQL pattern uses JDBC-style bare placeholders, e.g. \"nvl(?, ?)\" or \"coalesce(?,?)\" instead of Hibernate's \"nvl(?1, ?2)\"; or a trailing '?' at the end of a pattern like \"mod(?1, ?)\".","commonSituations":"Porting native SQL snippets verbatim into pattern-based registrations; Hibernate 5 to 6 migration where patterns must now use numbered placeholders; typos introduced while editing long SQL patterns.","solutions":["Number every placeholder in the pattern: ?1, ?2, ... (repeat a number to render the same argument twice).","If a '?' is meant literally (e.g. a JSON operator), restructure the pattern so no bare '?' remains next to the placeholder syntax.","Construct the renderer in a unit test for every registered pattern so the failure happens in CI, not at boot."],"exampleFix":"// before - JDBC-style placeholders, no indexes\nnew PatternBasedSqmFunctionDescriptor(..., \"nvl(?, ?)\", ...)\n\n// after - numbered placeholders\nnew PatternBasedSqmFunctionDescriptor(..., \"nvl(?1, ?2)\", ...)","handlingStrategy":"validation","validationCode":"static void assertPatternPlaceholders(String pattern) {\n    for (int i = 0; i < pattern.length(); i++) {\n        if (pattern.charAt(i) == '?'\n                && (i + 1 >= pattern.length() || !Character.isDigit(pattern.charAt(i + 1)))) {\n            throw new IllegalArgumentException(\"Bare '?' at index \" + i + \" in pattern: \" + pattern);\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    new PatternRenderer(pattern);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"Bad SQL pattern for function '\" + name + \"': '\" + pattern + \"'\", e);\n}","preventionTips":["Every '?' in a Hibernate 6 function SQL pattern must be immediately followed by its 1-based argument number.","Construct renderers for all registered patterns in unit tests so bad patterns fail the build, not application boot.","Never copy JDBC-style '?' placeholders from native SQL into a pattern verbatim."],"tags":["hibernate","pattern-renderer","function-registration","sql-pattern","bootstrap"],"backgroundTag":"invalid-function-pattern","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}