JetBrains/intellij-community · error · EvaluateRuntimeException

Variable ''{0}'' is already declared

Error message

Variable ''{0}'' is already declared

What it means

Thrown by CodeFragmentEvaluator.setInitialValue when code that builds an evaluation tries to register a synthetic local variable under a name that already exists in the current code fragment evaluator. It guards against silently shadowing an existing evaluation variable with a non-JDI seed value.

Source

Thrown at java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CodeFragmentEvaluator.java:100

  boolean hasValue(String localName) {
    if (!mySyntheticLocals.containsKey(localName)) {
      if (myParentFragmentEvaluator != null) {
        return myParentFragmentEvaluator.hasValue(localName);
      }
      else {
        return false;
      }
    }
    else {
      return true;
    }
  }

  public void setInitialValue(String localName, Object value) {
    LOG.assertTrue(!(value instanceof Value), "use setValue for jdi values");
    if (hasValue(localName)) {
      throw new EvaluateRuntimeException(
        EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.variable.already.declared", localName)));
    }
    mySyntheticLocals.put(localName, value);
  }

  public void setValue(String localName, Value value) throws EvaluateException {
    if (!mySyntheticLocals.containsKey(localName)) {
      if (myParentFragmentEvaluator != null) {
        myParentFragmentEvaluator.setValue(localName, value);
      }
      else {
        throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.variable.not.declared", localName));
      }
    }
    else {
      mySyntheticLocals.put(localName, value);
    }
  }

View on GitHub (pinned to be881553f2)

Solutions

  1. Use a unique variable name for each setInitialValue call
  2. Check hasValue(localName) before calling setInitialValue and use setValue for existing JDI values
  3. Create a fresh CodeFragmentEvaluator per evaluation instead of reusing one

Example fix

// before
fragment.setInitialValue("x", 1);
fragment.setInitialValue("x", 2); // throws

// after
if (fragment.hasValue("x")) {
  fragment.setValue("x", debuggerValue);
} else {
  fragment.setInitialValue("x", 1);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!fragment.hasValue(localName)) {
  fragment.setInitialValue(localName, value);
} else {
  fragment.setValue(localName, jdiValue); // or pick another name
}

Try / catch

try {
  evaluator.setInitialValue(name, value);
} catch (EvaluateRuntimeException e) {
  if (e.getMessage().contains("already declared")) { /* rename variable */ }
}

Prevention

When it happens

Trigger: Calling setInitialValue(localName, value) twice with the same localName on the same CodeFragmentEvaluator, or registering a name already added by a previous statement; hasValue(localName) returns true and an EvaluateRuntimeException wrapping evaluation.error.variable.already.declared is thrown.

Common situations: Debugger internals or plugins (e.g. JVM debugger language injection, Groovy/Kotlin evaluators reusing fragments) that seed the same captured variable name twice; re-evaluating an expression against a reused evaluator instance without resetting synthetic locals.

Related errors


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