JetBrains/intellij-community · error · ContractConversionException
changeSignature.contract.converter.return.parameter.removed
changeSignature.contract.converter.return.parameter.removed
Error message
Parameter '{0}' was deleted, but contract clause '{1}' returns it What it means
Thrown by the private convertContract in ContractConverter when a contract clause's return value is a parameter reference (e.g. '-> param1') and Change Signature deletes exactly that parameter (oldToNewIndex[oldIndex] == -1). The clause promises to return an argument the new signature no longer has, so conversion is refused.
Source
Thrown at java/java-impl/src/com/intellij/refactoring/changeSignature/ContractConverter.java:96
oldParameterNames[i], contract);
throw new ContractConversionException(paramRemovedMessage);
}
}
StandardMethodContract.ValueConstraint[] newConstraints = IntStreamEx.of(newToOldIndex)
.mapToObj(idx -> idx == -1 ? StandardMethodContract.ValueConstraint.ANY_VALUE : contract.getParameterConstraint(idx))
.toArray(StandardMethodContract.ValueConstraint.class);
ContractReturnValue returnValue = contract.getReturnValue();
if (returnValue instanceof ContractReturnValue.ParameterReturnValue) {
int oldIndex = ((ContractReturnValue.ParameterReturnValue)returnValue).getParameterNumber();
if (oldIndex >= contract.getParameterCount()) {
String errorRefMessage = JavaRefactoringBundle.message("changeSignature.contract.converter.invalid.return.reference", returnValue);
throw new ContractConversionException(errorRefMessage);
}
int index = oldToNewIndex[oldIndex];
if (index == -1) {
String paramRemovedMessage = JavaRefactoringBundle.message("changeSignature.contract.converter.return.parameter.removed",
oldParameterNames[oldIndex], contract);
throw new ContractConversionException(paramRemovedMessage);
}
returnValue = ContractReturnValue.returnParameter(index);
}
return new StandardMethodContract(newConstraints, returnValue);
}
private static int[] reverseIndex(int oldParameterCount, int[] newToOldIndex) {
int[] oldToNewIndex = new int[oldParameterCount];
Arrays.fill(oldToNewIndex, -1);
for (int i = 0; i < newToOldIndex.length; i++) {
int oldIndex = newToOldIndex[i];
if (oldIndex >= 0 && oldIndex < oldParameterCount) {
oldToNewIndex[oldIndex] = i;
}
}
return oldToNewIndex;
}
View on GitHub (pinned to be881553f2)
Solutions
- Change the contract's return value first: replace '-> paramK' with a static return ('-> new', '-> null') or delete the annotation, then run Change Signature.
- Keep the parameter if the return-the-argument semantics must be preserved.
- After manual contract cleanup, rerun the refactoring so remaining clauses convert automatically.
Example fix
// before: deleting 'b' throws
@Contract("null, _ -> param2")
Object f(String a, Object b) { return b; }
// after: adjust contract to the new signature
@Contract("null -> null")
Object f(String a) { return null; } Defensive patterns
Strategy: validation
Validate before calling
// before deleting parameter k, check the return value does not reference it
for (StandardMethodContract c : StandardMethodContract.parseContract(contractText)) {
ContractReturnValue rv = c.getReturnValue();
if (rv instanceof ContractReturnValue.ParameterReturnValue prv && prv.getParameterNumber() == k) {
// clause returns the parameter being deleted; change return value or keep the parameter
}
} Try / catch
try { ContractConverter.convertContract(method, info); } catch (ContractConversionException e) { /* if the deleted parameter is returned, change '-> paramK' or drop the annotation first */ } Prevention
- Check '-> paramN' return references before deleting any parameter via Change Signature.
- For passthrough methods (return an argument), keep the parameter or rewrite the contract return.
- Review contracts as part of the checklist for any signature-affecting refactoring.
When it happens
Trigger: Running Change Signature that removes parameter k on a method with @Contract("... -> paramK"); e.g. deleting 'b' from @Contract("null, _ -> param2") Object f(String a, Object b).
Common situations: API cleanup deleting a passthrough parameter that the contract returns; wrapper/delegate methods annotated with param-returning contracts; batch parameter removal ignoring annotations.
Related errors
- changeSignature.contract.converter.parameter.removed
- changeSignature.contract.converter.external.annotations
- changeSignature.contract.converter.inherited.annotation
- changeSignature.contract.converter.mutation.contract
- changeSignature.contract.converter.definition.error
AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14).
Data as JSON: /api/errors/44318e91ba0b65e6.
Report an issue: GitHub.