{"record":{"id":"3d5ea644f769dc1c","repo":"hibernate/hibernate-orm","slug":"cannot-mix-named-parameter-with-positional-paramet","errorCode":null,"errorMessage":"Cannot mix named parameter with positional parameter registrations","messagePattern":"Cannot mix named parameter with positional parameter registrations","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterMetadataImpl.java","lineNumber":44,"sourceCode":"import static java.util.Collections.emptyList;\nimport static java.util.Collections.emptySet;\nimport static java.util.Collections.unmodifiableList;\n\n/**\n * Specialized ParameterMetadataImplementor for callable queries implementing\n * expandable parameter registrations\n *\n * @author Steve Ebersole\n */\nclass ProcedureParameterMetadataImpl implements ProcedureParameterMetadataImplementor {\n\tprivate ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;\n\tprivate List<ProcedureParameterImplementor<?>> parameters;\n\n\t@Override\n\tpublic void registerParameter(ProcedureParameterImplementor<?> parameter) {\n\t\tif ( parameter.isNamed() ) {\n\t\t\tif ( parameterStrategy == ParameterStrategy.POSITIONAL ) {\n\t\t\t\tthrow new IllegalArgumentException( \"Cannot mix named parameter with positional parameter registrations\" );\n\t\t\t}\n\t\t\tparameterStrategy = ParameterStrategy.NAMED;\n\t\t}\n\t\telse if ( parameter.isOrdinal() ) {\n\t\t\tif ( parameterStrategy == ParameterStrategy.NAMED ) {\n\t\t\t\tthrow new IllegalArgumentException( \"Cannot mix positional parameter with named parameter registrations\" );\n\t\t\t}\n\t\t\tparameterStrategy = ParameterStrategy.POSITIONAL;\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException( \"Unrecognized parameter type : \" + parameter );\n\t\t}\n\t\tif ( parameters == null ) {\n\t\t\tparameters = new ArrayList<>();\n\t\t}\n\t\tparameters.add( parameter );\n\t}\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterMetadataImpl.java#L26-L62","documentation":"A ProcedureCall keeps exactly one ParameterStrategy (NAMED or POSITIONAL) for its whole parameter list. ProcedureParameterMetadataImpl.registerParameter throws IllegalArgumentException 'Cannot mix named parameter with positional parameter registrations' the moment a named registration arrives after a positional one was already registered. The JDBC call string is rendered with a single parameter style, so mixing is rejected up front.","triggerScenarios":"call.registerParameter(1, String.class, ParameterMode.IN) followed by call.registerParameter(\"mode\", String.class, ParameterMode.IN) on the same ProcedureCall; or Jakarta query.registerStoredProcedureParameter(1, ...) followed by a named registerStoredProcedureParameter(\"mode\", ...).","commonSituations":"Copy-pasting snippets that use different registration styles; framework or wrapper code appending audit parameters by name while user code registered positionally; halfway migrations from positional to named parameters; one shared helper used for calls that were written in different styles.","solutions":["Rewrite all registrations for that call into one style — either all positional or all named","Audit every registerParameter / registerStoredProcedureParameter call that touches the same ProcedureCall instance","If named parameters are wanted, convert the positional registrations to named and use names the database procedure actually accepts"],"exampleFix":"// before\ncall.registerParameter(1, Long.class, ParameterMode.IN);\ncall.registerParameter(\"comment\", String.class, ParameterMode.IN); // mixing!\n\n// after\ncall.registerParameter(1, Long.class, ParameterMode.IN);\ncall.registerParameter(2, String.class, ParameterMode.IN);","handlingStrategy":"validation","validationCode":"// Enforce one style per call inside a helper\nprivate static void register(ProcedureCall call, boolean positional, Object id, Class<?> type, ParameterMode mode) {\n    if (positional) {\n        call.registerParameter((Integer) id, type, mode);\n    } else {\n        call.registerParameter((String) id, type, mode);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    call.registerParameter(\"mode\", String.class, ParameterMode.IN);\n} catch (IllegalArgumentException e) {\n    // style conflict: convert the registration to whichever style this call already uses\n}","preventionTips":["Choose named or positional for the whole procedure call; never mix within one call","Centralize registrations in a single helper that takes the style once","Code-review procedure call setups for stray registrations of the other style"],"tags":["hibernate","stored-procedure","parameter-binding","api-misuse"],"backgroundTag":"mixed-named-positional-parameters","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}