bazelbuild/bazel · error · EvalException

Starlark computation cancelled: too many steps

Error message

Starlark computation cancelled: too many steps

What it means

Starlark executes scripts within a step budget: every executed statement increments a counter, and when it reaches the thread's stepLimit the interpreter aborts with EvalException 'Starlark computation cancelled: too many steps'. This is a safety valve against infinite loops, since Starlark has no other resource control for unbounded loops. This instance is the check in statement execution (exec).

Source

Thrown at src/main/java/net/starlark/java/eval/Eval.java:326

    // Assign a value to the type alias identifier only if type tagging is enabled.
    if (typeTable != null) {
      TypeConstructor typeConstructor =
          checkNotNull(typeTable.getTypeConstructor(node.getIdentifier().getBinding()));
      assignIdentifier(fr, node.getIdentifier(), TypeConstructorValue.of(typeConstructor));
    }
    return TokenKind.PASS;
  }

  private static TokenKind exec(StarlarkThread.Frame fr, Statement st)
      throws EvalException, InterruptedException {
    if (fr.dbg != null) {
      Location loc = st.getStartLocation(); // not very precise
      fr.setLocation(loc);
      fr.dbg.before(fr.thread, loc); // location is now redundant since it's in the thread
    }

    if (++fr.thread.steps >= fr.thread.stepLimit) {
      throw new EvalException("Starlark computation cancelled: too many steps");
    }

    switch (st.kind()) {
      case ASSIGNMENT:
        execAssignment(fr, (AssignmentStatement) st);
        return TokenKind.PASS;
      case EXPRESSION:
        eval(fr, ((ExpressionStatement) st).getExpression());
        return TokenKind.PASS;
      case FLOW:
        return ((FlowStatement) st).getFlowKind();
      case FOR:
        return execFor(fr, (ForStatement) st);
      case DEF:
        DefStatement def = (DefStatement) st;
        StarlarkFunction fn = newFunction(fr, def.getResolvedFunction());
        assignIdentifier(fr, def.getIdentifier(), fn);
        return TokenKind.PASS;

View on GitHub (pinned to e6e199d060)

Solutions

  1. Fix the script: ensure loop termination conditions actually progress (bump the counter/index, correct the break condition).
  2. If the computation is legitimately large, raise the budget: StarlarkThread.setStepLimit(n) (or the host application's configured limit) before evaluation.
  3. Reproduce locally with a debug print/log every N iterations to find the non-terminating loop.
  4. Move the heavy computation into a native (Java) Starlark builtin instead of a Starlark loop.

Example fix

# before
def collect(items):
    out = []
    i = 0
    while i < len(items):   # i never incremented -> infinite
        out.append(items[i])
    return out

# after
def collect(items):
    return list(items)
Defensive patterns

Strategy: try-catch

Try / catch

try {
  Starlark.execFile(thread, parsedFile);
} catch (EvalException e) {
  if (e.getMessage().contains("too many steps")) {
    // script exceeded budget: fix the loop or raise setStepLimit
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: A script with an unbounded or huge loop (while True:, for over an enormous range/list), runaway recursion expressed iteratively, or a legitimately long computation whose step count exceeds the configured limit; StarlarkThread.stepLimit set low or left at default.

Common situations: BUILD/.bzl or macro logic with a loop over all targets that grows with the repository; regression where a loop condition never becomes false; evaluators (REPL, tests) running with a small stepLimit for fast failure.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/1dda34d04d3761ae. Report an issue: GitHub.