JetBrains/intellij-community · error · EvaluateException

Unable to do foreach for

Error message

Unable to do foreach for

What it means

Thrown by ForeachStatementEvaluator.evaluate when the iterable expression of an enhanced-for loop in the evaluated fragment evaluates to something that is not an ObjectReference in the debuggee VM (null, a raw primitive, a void result). Without an ObjectReference (ArrayReference or Iterable object) the foreach machinery cannot iterate, so it aborts. Note the missing space in the original message concatenation.

Solutions

  1. Check the iterable is non-null and is an array or Iterable before the loop: for (x : Objects.requireNonNull(list))
  2. For maps, iterate map.entrySet() or map.keySet() instead of the map itself
  3. Step the debugger to a point where the collection is initialized, then evaluate

Example fix

// before: for (String s : names) { ... }  // names is null

// after: for (String s : java.util.List.of("a")) { ... }
// or evaluate later, after names is assigned
Defensive patterns

Strategy: validation

Validate before calling

Object iterable = iterableEvaluator.evaluate(context);
if (!(iterable instanceof ObjectReference)) {
  throw new EvaluateException("Unable to do foreach for " + iterable);
}
// guard before: check the collection variable is non-null at this breakpoint

Type guard

static boolean isForeachable(Object evaluated) {
  return evaluated instanceof ObjectReference; // ArrayReference or Iterable mirror
}

Try / catch

try {
  foreachEvaluator.evaluate(context);
} catch (EvaluateException e) {
  // inspect the iterable expression alone; if null, skip the loop
}

Prevention

When it happens

Trigger: Evaluating 'for (x : expr) {...}' where myIterableEvaluator.evaluate(context) returns null (NPE in the evaluated provider, method returned void) or a PrimitiveValue; instanceof ObjectReference fails and EvaluateException('Unable to do foreach for' + iterable) is thrown.

Common situations: Evaluating a foreach over a variable that is null at the breakpoint; iterating over a primitive-typed expression; the iterable's getter threw inside the debuggee and the evaluator propagated null; evaluating a foreach over a Map instead of map.entrySet().

Related errors


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

Appendix: source

Thrown at java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ForeachStatementEvaluator.java:32

  private final Evaluator myIterableEvaluator;
  private final Evaluator myBodyEvaluator;
  private final String myLabelName;

  public ForeachStatementEvaluator(Evaluator iterationParameterEvaluator,
                                   Evaluator iterableEvaluator,
                                   Evaluator bodyEvaluator,
                                   String labelName) {
    myIterationParameterEvaluator = iterationParameterEvaluator;
    myIterableEvaluator = DisableGC.create(iterableEvaluator);
    myBodyEvaluator = bodyEvaluator;
    myLabelName = labelName;
  }

  @Override
  public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
    final Object iterable = myIterableEvaluator.evaluate(context);
    if (!(iterable instanceof ObjectReference)) {
      throw new EvaluateException("Unable to do foreach for" + iterable);
    }

    if (iterable instanceof ArrayReference) {
      return new ForStatementEvaluatorBase(myLabelName, myBodyEvaluator) {
        private int myCurrentIndex = 0;
        private int myArrayLength = -1;
        private Evaluator myNextEvaluator;

        @Override
        protected Object evaluateInitialization(EvaluationContextImpl context, Object value) throws EvaluateException {
          myArrayLength = ((ArrayReference)iterable).length();
          myNextEvaluator = new AssignmentEvaluator(myIterationParameterEvaluator,
                                                    new Evaluator() {
                                                      @Override
                                                      public Object evaluate(EvaluationContextImpl context) {
                                                        return ((ArrayReference)iterable).getValue(myCurrentIndex++);
                                                      }
                                                    });

View on GitHub (pinned to be881553f2)