openclaw/openclaw · error

Batch exceeds maximum of ${ACT_MAX_BATCH_ACTIONS} actions

Error message

Batch exceeds maximum of ${ACT_MAX_BATCH_ACTIONS} actions

What it means

Thrown by batchViaPlaywright when a batch's actions array length exceeds ACT_MAX_BATCH_ACTIONS (currently 100). This caps execution-budget growth, transport-timeout pressure, and result-payload size. The same limit is enforced upstream in agent.act.normalize.ts so oversized batches are rejected before reaching Playwright.

Source

Thrown at extensions/browser/src/browser/pw-tools-core.interactions.execution.ts:381

  }
}

export async function batchViaPlaywright(
  opts: GuardedInteractionOptions & {
    actions: BrowserActRequest[];
    stopOnError?: boolean;
    evaluateEnabled?: boolean;
    depth?: number;
    page?: Page;
  },
): Promise<{ results: BrowserBatchActionResult[]; aborted?: BrowserBatchAbort }> {
  const navigationPolicy = interactionNavigationPolicy(opts);
  const depth = opts.depth ?? 0;
  if (depth > ACT_MAX_BATCH_DEPTH) {
    throw new Error(`Batch nesting depth exceeds maximum of ${ACT_MAX_BATCH_DEPTH}`);
  }
  if (opts.actions.length > ACT_MAX_BATCH_ACTIONS) {
    throw new Error(`Batch exceeds maximum of ${ACT_MAX_BATCH_ACTIONS} actions`);
  }
  const page = opts.page ?? (await getPageForTargetId(opts));
  const results: BrowserBatchActionResult[] = [];
  const finishAborted = (
    reason: BrowserBatchAbort["reason"],
    afterAction: number,
    url: string,
    skipped: number,
  ) =>
    skipped === 0
      ? { results }
      : { results, aborted: { reason, afterAction, url, skipped } satisfies BrowserBatchAbort };
  let mainFrameNavigations = 0;
  let navigationsAtLastDispatch = 0;
  const currentMainFrameUrl = () => page.mainFrame?.().url() ?? page.url();
  const onFrameNavigated = (frame: Frame) => {
    if (frame === page.mainFrame?.()) {
      mainFrameNavigations += 1;

View on GitHub (pinned to 01804a7531)

Solutions

  1. Split the batch into multiple calls of at most 100 actions each and submit them sequentially.
  2. Reduce the action count by combining related steps (e.g., use fill with multiple fields instead of individual type actions).
  3. Count actions client-side before submission and chunk automatically.

Example fix

// before — 150 actions in one batch
{ kind: "batch", actions: [/* 150 click actions */] }
// after — two batches of <=100
await executeActViaPlaywright({ cdpUrl, action: { kind: "batch", actions: first100 } });
await executeActViaPlaywright({ cdpUrl, action: { kind: "batch", actions: next50 } });
Defensive patterns

Strategy: validation

Validate before calling

const ACT_MAX_BATCH_ACTIONS = 100;
function chunkBatch<T>(actions: T[], size = ACT_MAX_BATCH_ACTIONS): T[][] {
  const chunks: T[][] = [];
  for (let i = 0; i < actions.length; i += size) {
    chunks.push(actions.slice(i, i + size));
  }
  return chunks;
}
// Before submitting:
if (action.actions.length > ACT_MAX_BATCH_ACTIONS) {
  for (const chunk of chunkBatch(action.actions)) {
    await executeActViaPlaywright({ cdpUrl, action: { kind: "batch", actions: chunk }, evaluateEnabled });
  }
}

Prevention

When it happens

Trigger: Submitting a batch action with opts.actions.length > 100. Also fires when a model or loop emits a very large batch without chunking.

Common situations: Bulk form-filling with hundreds of fields. Scraping flows that batch one action per item across large lists. Models that try to 'do everything in one call' by stuffing all steps into a single batch.

Related errors


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/f2e52db5a6e6e2a6. Report an issue: GitHub.