JetBrains/intellij-community · error · IncorrectOperationException

cannot handle content change for:

Error message

cannot handle content change for: 

What it means

StringLiteralManipulator.handleContentChange rewrites the value of a PsiLiteralExpression (string or char literal). It escapes content for text blocks and '"'-delimited strings, and allows at most one character for "'"-delimited char literals. Any other combination — no leading quote, or multi-character content in a char literal — throws IncorrectOperationException("cannot handle content change for: ...").

Source

Thrown at java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/StringLiteralManipulator.java:32

import com.intellij.psi.util.PsiLiteralUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;

public final class StringLiteralManipulator extends AbstractElementManipulator<PsiLiteralExpression> {
  @Override
  public PsiLiteralExpression handleContentChange(@NotNull PsiLiteralExpression expr, @NotNull TextRange range, String newContent) throws IncorrectOperationException {
    String oldText = expr.getText();
    if (expr.isTextBlock()) {
      newContent = escapeTextBlockContent(newContent);
    }
    else if (oldText.startsWith("\"")) {
      newContent = StringUtil.escapeStringCharacters(newContent);
    }
    else if (oldText.startsWith("'") && newContent.length() <= 1) {
      newContent = newContent.length() == 1 && newContent.charAt(0) == '\''? "\\'" : newContent;
    }
    else {
      throw new IncorrectOperationException("cannot handle content change for: " + oldText + ", expr: " + expr);
    }

    String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset());
    final PsiExpression newExpr = JavaPsiFacade.getElementFactory(expr.getProject()).createExpressionFromText(newText, null);
    return (PsiLiteralExpression)expr.replace(newExpr);
  }

  private static @NotNull String escapeTextBlockContent(@NotNull String content) {
    String[] lines = PsiLiteralUtil.escapeTextBlockCharacters(content, false, true, false).split("(?<=\n)");
    int indent = PsiLiteralUtil.getTextBlockIndent(lines, true, true);
    if (indent != 0 && lines.length > 0 && !lines[lines.length - 1].endsWith("\n")) {
      // append \ + newline at the end of the last line, so we can use closing """ to indent;
      lines[lines.length - 1] += "\\\n";
    }
    for (int i = 0; i < lines.length - 1; i++) {
      String line = lines[i];
      if (line.endsWith("\\\n") && lines[i + 1].equals("\n")) {
        lines[i] = line.substring(0, line.length() - 2); // normalize strings with leading newlines

View on GitHub (pinned to be881553f2)

Solutions

  1. Validate before editing: if literal text starts with "'" ensure newContent.length() <= 1 (escape the single quote via "\\'" as the manipulator does).
  2. For multi-character content, convert the char literal to a string literal first (replace with '"'-quoted expression), then apply the content change.
  3. If the literal's text has no quotes, repair the PSI (reparse) before manipulating, or replace the element wholesale via PsiElementFactory.

Example fix

// before
ElementManipulators.handleContentChange(charLiteral, "ab"); // char literal, 2 chars -> throws

// after
PsiExpression replacement = newContent.length() <= 1 && charLiteral.getText().startsWith("'")
    ? ElementManipulators.handleContentChange(charLiteral, newContent)
    : (PsiExpression)charLiteral.replace(factory.createExpressionFromText("\"" + StringUtil.escapeStringCharacters(newContent) + "\"", null));
Defensive patterns

Strategy: validation

Validate before calling

String old = literal.getText();
if (old.startsWith("'") && newContent.length() > 1) return; // char literal cannot hold 2+ chars

Try / catch

try { ElementManipulators.handleContentChange(literal, c); } catch (IncorrectOperationException e) { /* convert char to string literal first */ }

Prevention

When it happens

Trigger: Calling ElementManipulators.handleContentChange(literal, newContent) on a char literal with newContent.length() > 1, or on a PsiLiteralExpression whose text lacks quotes (broken PSI after failed parsing, or non-literal expressions misreported as literals).

Common situations: Intention 'replace string with char' style edits feeding multi-char text; language injection rewriters that call the manipulator generically on all literal expressions; unit tests mutating literals with arbitrary strings.

Related errors


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