JetBrains/intellij-community · error · ContractConversionException

changeSignature.contract.converter.definition.error

changeSignature.contract.converter.definition.error

Error message

Error in contract definition: {0}

What it means

Thrown by ContractConverter.convertContract when the inline @Contract value cannot be parsed by StandardMethodContract.parseContract. The annotation text is syntactically invalid as a contract expression, so conversion is impossible; the underlying ParseException message is embedded. This indicates the annotation value itself is malformed, independent of the refactoring.

Source

Thrown at java/java-impl/src/com/intellij/refactoring/changeSignature/ContractConverter.java:53

    if (AnnotationUtil.isExternalAnnotation(annotation)) {
      throw new ContractConversionException(JavaRefactoringBundle.message("changeSignature.contract.converter.external.annotations"));
    }
    if (annotation.getOwner() != method.getModifierList()) {
      throw new ContractInheritedException();
    }
    if (annotation.findDeclaredAttributeValue(MutationSignature.ATTR_MUTATES) != null) {
      throw new ContractConversionException(JavaRefactoringBundle.message("changeSignature.contract.converter.mutation.contract"));
    }
    String text = AnnotationUtil.getStringAttributeValue(annotation, null);
    List<StandardMethodContract> contracts = Collections.emptyList();
    if (text != null) {
      try {
        contracts = StandardMethodContract.parseContract(text);
      }
      catch (StandardMethodContract.ParseException exception) {
        String definitionError = JavaRefactoringBundle.message("changeSignature.contract.converter.definition.error",
                                                               exception.getMessage());
        throw new ContractConversionException(definitionError);
      }
    }
    int[] newToOldIndex = StreamEx.of(newParameters).mapToInt(ParameterInfo::getOldIndex).toArray();
    int[] oldToNewIndex = reverseIndex(oldParameterNames.length, newToOldIndex);

    List<StandardMethodContract> result = new ArrayList<>();
    for (StandardMethodContract contract : contracts) {
      result.add(convertContract(contract, newToOldIndex, oldToNewIndex, oldParameterNames));
    }
    if (result.equals(contracts)) return annotation;
    return JavaMethodContractUtil.updateContract(annotation, result);
  }

  private static @NotNull StandardMethodContract convertContract(@NotNull StandardMethodContract contract,
                                                                 int @NotNull [] newToOldIndex,
                                                                 int @NotNull [] oldToNewIndex,
                                                                 String @NotNull [] oldParameterNames) throws ContractConversionException {
    if (contract.getParameterCount() != oldToNewIndex.length) {

View on GitHub (pinned to be881553f2)

Solutions

  1. Fix the @Contract value so every clause is '<constraint,constraint,...> -> <return>' with constraint names from StandardMethodContract (null, !null, true, false, _, fail, new, this, paramN) and semicolons between clauses.
  2. Ensure the number of comma-separated constraints equals the method's parameter count in each clause.
  3. Let the IDE's '@Contract syntax error' inspection highlight the problem first, then rerun Change Signature.

Example fix

// before
@Contract("nul -> false")
boolean check(String s) { ... }
// after
@Contract("null -> false")
boolean check(@Nullable String s) { ... }
Defensive patterns

Strategy: validation

Validate before calling

String text = AnnotationUtil.getStringAttributeValue(annotation, null);
if (text != null) {
  try { StandardMethodContract.parseContract(text); }
  catch (StandardMethodContract.ParseException e) { /* annotation is malformed; fix before refactoring */ }
}

Try / catch

try { ContractConverter.convertContract(method, info); } catch (ContractConversionException e) { /* message embeds parse error; fix the @Contract string, then re-run */ }

Prevention

When it happens

Trigger: Refactoring a method with @Contract("foo -> bar") (unknown constraint names), @Contract("null -> new") (bad return value), unbalanced '->', wrong clause separator ';', or wrong arity like 'null, null -> true; true, null -> false' with mismatched parameter counts.

Common situations: Typos in hand-written contract strings; contracts written for a different parameter count after earlier edits; copy-paste from documentation with wrong clause syntax; inspection warnings ignored before running the refactoring.

Related errors


AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14). Data as JSON: /api/errors/625f8b4c850f0c71. Report an issue: GitHub.