{"record":{"id":"2e26703a7b2c543f","repo":"hibernate/hibernate-orm","slug":"in-parameter-not-valid-for-output-extraction","errorCode":null,"errorMessage":"IN parameter not valid for output extraction","messagePattern":"IN parameter not valid for output extraction","errorType":"exception","errorClass":"ParameterMisuseException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/procedure/internal/OutputsImpl.java","lineNumber":120,"sourceCode":"\t\t\ttry {\n\t\t\t\tupdateCount = jdbcStatement.getUpdateCount();\n\t\t\t}\n\t\t\tcatch (SQLException e) {\n\t\t\t\tthrow convert( e, \"Error calling CallableStatement.getUpdateCount\" );\n\t\t\t}\n\t\t}\n\n\t\treturn buildCurrentReturnState( isResultSet, updateCount );\n\t}\n\n\tprotected CurrentReturnState buildCurrentReturnState(boolean isResultSet, int updateCount) {\n\t\treturn new CurrentReturnState( this, isResultSet, updateCount );\n\t}\n\n\t@Override\n\tpublic <T> T getOutputParameterValue(ProcedureParameter<T> parameter) {\n\t\tif ( parameter.getMode() == ParameterMode.IN ) {\n\t\t\tthrow new ParameterMisuseException( \"IN parameter not valid for output extraction\" );\n\t\t}\n\t\tfinal var registration = parameterRegistrations.get( parameter );\n\t\tif ( registration == null ) {\n\t\t\tthrow new IllegalArgumentException( \"Parameter [\" + parameter + \"] is not registered with this procedure call\" );\n\t\t}\n\t\ttry {\n\t\t\tif ( registration.getParameterMode() == ParameterMode.REF_CURSOR ) {\n\t\t\t\t//noinspection unchecked\n\t\t\t\treturn (T) registration.getRefCursorExtractor().extractResultSet(\n\t\t\t\t\t\tjdbcStatement,\n\t\t\t\t\t\tprocedureCall.getSession()\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t//noinspection unchecked\n\t\t\t\treturn (T) registration.getParameterExtractor().extractValue(\n\t\t\t\t\t\tjdbcStatement,\n\t\t\t\t\t\tparameter.getPosition() == null,","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/procedure/internal/OutputsImpl.java#L102-L138","documentation":"OutputsImpl.getOutputParameterValue(ProcedureParameter) reads values the database wrote back after execution. Before extraction it checks parameter.getMode(); an IN-only parameter is never populated by the database, so there is no output value to read and Hibernate fails fast with ParameterMisuseException instead of returning garbage.","triggerScenarios":"storedProcedureQuery.getOutputParameterValue(param) where param was registered with ParameterMode.IN; the position/name overloads (getOutputParameterValue(1)) when that position is an IN parameter.","commonSituations":"Forgetting to declare INOUT/OUT on registration; positional miscounting after a function-return parameter shift; porting from drivers that tolerated reading IN values; reading back a value you only intended to bind.","solutions":["Register the parameter as INOUT (registerStoredProcedureParameter(1, Integer.class, ParameterMode.INOUT)) so the database returns the final value.","Only call getOutputParameterValue for parameters whose getMode() is OUT, INOUT or REF_CURSOR.","If you only need the value you bound, use your own variable instead of extracting it."],"exampleFix":"// before\nproc.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);\nproc.setParameter(1, 42);\nproc.execute();\nint n = (Integer) proc.getOutputParameterValue(1); // throws\n\n// after\nproc.registerStoredProcedureParameter(1, Integer.class, ParameterMode.INOUT);\nproc.setParameter(1, 42);\nproc.execute();\nint n = (Integer) proc.getOutputParameterValue(1);","handlingStrategy":"validation","validationCode":"// only extract parameters the database actually writes back\nStoredProcedureParameter<?> target = proc.getParameters().stream()\n        .filter( p -> Objects.equals( p.getPosition(), position ) )\n        .findFirst().orElse( null );\nif ( target == null || target.getMode() == ParameterMode.IN ) {\n    throw new IllegalArgumentException( \"position \" + position + \" is not an output parameter\" );\n}\nObject value = proc.getOutputParameterValue( position );","typeGuard":"static boolean isExtractable(StoredProcedureParameter<?> p) {\n    return p.getMode() == ParameterMode.OUT\n            || p.getMode() == ParameterMode.INOUT\n            || p.getMode() == ParameterMode.REF_CURSOR;\n}","tryCatchPattern":"try {\n    Object v = proc.getOutputParameterValue( param );\n} catch (ParameterMisuseException e) {\n    // the parameter is IN-only; nothing to read back\n}","preventionTips":["Register every parameter you intend to read back as INOUT or OUT.","Check getMode() before extraction in generic extraction loops.","Never assume the value you bound is readable; keep it in a local variable."],"tags":["hibernate","stored-procedure","parameter-mode","output-parameter"],"backgroundTag":"stored-procedure-parameter-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}