{"record":{"id":"457805862f2bd246","repo":"JetBrains/intellij-community","slug":"changesignature-contract-converter-invalid-return","errorCode":"changeSignature.contract.converter.invalid.return.reference","errorMessage":"Invalid reference in return value: {0}","messagePattern":"Invalid reference in return value: (.+?)","errorType":"exception","errorClass":"ContractConversionException","httpStatus":null,"severity":"error","filePath":"java/java-impl/src/com/intellij/refactoring/changeSignature/ContractConverter.java","lineNumber":90,"sourceCode":"      // invalid contract\n      throw new ContractConversionException(JavaRefactoringBundle.message(\"changeSignature.contract.converter.invalid.clause\", contract));\n    }\n    for (int i = 0; i < contract.getParameterCount(); i++) {\n      if (contract.getParameterConstraint(i) != StandardMethodContract.ValueConstraint.ANY_VALUE && oldToNewIndex[i] == -1) {\n        String paramRemovedMessage = JavaRefactoringBundle.message(\"changeSignature.contract.converter.parameter.removed\",\n                                                                   oldParameterNames[i], contract);\n        throw new ContractConversionException(paramRemovedMessage);\n      }\n    }\n    StandardMethodContract.ValueConstraint[] newConstraints = IntStreamEx.of(newToOldIndex)\n                                                                         .mapToObj(idx -> idx == -1 ? StandardMethodContract.ValueConstraint.ANY_VALUE : contract.getParameterConstraint(idx))\n                                                                         .toArray(StandardMethodContract.ValueConstraint.class);\n    ContractReturnValue returnValue = contract.getReturnValue();\n    if (returnValue instanceof ContractReturnValue.ParameterReturnValue) {\n      int oldIndex = ((ContractReturnValue.ParameterReturnValue)returnValue).getParameterNumber();\n      if (oldIndex >= contract.getParameterCount()) {\n        String errorRefMessage = JavaRefactoringBundle.message(\"changeSignature.contract.converter.invalid.return.reference\", returnValue);\n        throw new ContractConversionException(errorRefMessage);\n      }\n      int index = oldToNewIndex[oldIndex];\n      if (index == -1) {\n        String paramRemovedMessage = JavaRefactoringBundle.message(\"changeSignature.contract.converter.return.parameter.removed\",\n                                                                   oldParameterNames[oldIndex], contract);\n        throw new ContractConversionException(paramRemovedMessage);\n      }\n      returnValue = ContractReturnValue.returnParameter(index);\n    }\n    return new StandardMethodContract(newConstraints, returnValue);\n  }\n\n  private static int[] reverseIndex(int oldParameterCount, int[] newToOldIndex) {\n    int[] oldToNewIndex = new int[oldParameterCount];\n    Arrays.fill(oldToNewIndex, -1);\n    for (int i = 0; i < newToOldIndex.length; i++) {\n      int oldIndex = newToOldIndex[i];\n      if (oldIndex >= 0 && oldIndex < oldParameterCount) {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/JetBrains/intellij-community/blob/be881553f2a76ac8b4ea53950d93f0de78295c19/java/java-impl/src/com/intellij/refactoring/changeSignature/ContractConverter.java#L72-L108","documentation":"Thrown by the private convertContract in ContractConverter when a @Contract clause's return value references a parameter by number (ParameterReturnValue, e.g. '-> param1') but that number is out of range for the clause's parameter count. The return value points at a parameter that does not exist in the parsed clause, indicating a corrupt or stale contract clause.","triggerScenarios":"A contract like @Contract(\"null -> param2\") on a 2-parameter method (param index beyond the constraint list), or '-> param1' where the clause lists constraints for a different arity; running Change Signature then trips the index check oldIndex >= contract.getParameterCount().","commonSituations":"Hand-written paramN references miscounted from 1; parameters removed earlier leaving paramN pointing past the end; contract strings copied between similar methods with different parameter counts.","solutions":["Fix the return reference: paramN is 1-based, so for a method with N parameters only '-> param1'..\"-> paramN\" are valid.","Align the clause's constraint count with the parameter count and the paramN reference with an existing parameter.","Re-run Change Signature once the contract parses consistently."],"exampleFix":"// before (2 params, references 3rd)\n@Contract(\"null, null -> param3\")\nObject f(Object a, Object b) { ... }\n// after\n@Contract(\"_, null -> param2\")\nObject f(Object a, Object b) { return b; }","handlingStrategy":"validation","validationCode":"for (StandardMethodContract c : StandardMethodContract.parseContract(contractText)) {\n  ContractReturnValue rv = c.getReturnValue();\n  if (rv instanceof ContractReturnValue.ParameterReturnValue prv\n      && prv.getParameterNumber() > c.getParameterCount()) {\n    // out-of-range param reference; fix the return value\n  }\n}","typeGuard":null,"tryCatchPattern":"try { ContractConverter.convertContract(method, info); } catch (ContractConversionException e) { /* fix '-> paramN' to an in-range 1-based index, retry */ }","preventionTips":["Remember paramN in @Contract is 1-based and must be <= parameter count.","When copying contracts between methods, re-check param references against the target's arity.","Fix stale contracts immediately when parameters change, not at refactoring time."],"tags":["java","refactoring","change-signature","contract-annotation","return-value"],"backgroundTag":null,"analyzedSha":"be881553f2a76ac8b4ea53950d93f0de78295c19","analyzedAt":"2026-08-14T14:13:06.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}