{"record":{"id":"f2e52db5a6e6e2a6","repo":"openclaw/openclaw","slug":"batch-exceeds-maximum-of-act-max-batch-actions","errorCode":null,"errorMessage":"Batch exceeds maximum of ${ACT_MAX_BATCH_ACTIONS} actions","messagePattern":"Batch exceeds maximum of (.+?) actions","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extensions/browser/src/browser/pw-tools-core.interactions.execution.ts","lineNumber":381,"sourceCode":"  }\n}\n\nexport async function batchViaPlaywright(\n  opts: GuardedInteractionOptions & {\n    actions: BrowserActRequest[];\n    stopOnError?: boolean;\n    evaluateEnabled?: boolean;\n    depth?: number;\n    page?: Page;\n  },\n): Promise<{ results: BrowserBatchActionResult[]; aborted?: BrowserBatchAbort }> {\n  const navigationPolicy = interactionNavigationPolicy(opts);\n  const depth = opts.depth ?? 0;\n  if (depth > ACT_MAX_BATCH_DEPTH) {\n    throw new Error(`Batch nesting depth exceeds maximum of ${ACT_MAX_BATCH_DEPTH}`);\n  }\n  if (opts.actions.length > ACT_MAX_BATCH_ACTIONS) {\n    throw new Error(`Batch exceeds maximum of ${ACT_MAX_BATCH_ACTIONS} actions`);\n  }\n  const page = opts.page ?? (await getPageForTargetId(opts));\n  const results: BrowserBatchActionResult[] = [];\n  const finishAborted = (\n    reason: BrowserBatchAbort[\"reason\"],\n    afterAction: number,\n    url: string,\n    skipped: number,\n  ) =>\n    skipped === 0\n      ? { results }\n      : { results, aborted: { reason, afterAction, url, skipped } satisfies BrowserBatchAbort };\n  let mainFrameNavigations = 0;\n  let navigationsAtLastDispatch = 0;\n  const currentMainFrameUrl = () => page.mainFrame?.().url() ?? page.url();\n  const onFrameNavigated = (frame: Frame) => {\n    if (frame === page.mainFrame?.()) {\n      mainFrameNavigations += 1;","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/browser/src/browser/pw-tools-core.interactions.execution.ts#L363-L399","documentation":"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.","triggerScenarios":"Submitting a batch action with opts.actions.length > 100. Also fires when a model or loop emits a very large batch without chunking.","commonSituations":"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.","solutions":["Split the batch into multiple calls of at most 100 actions each and submit them sequentially.","Reduce the action count by combining related steps (e.g., use fill with multiple fields instead of individual type actions).","Count actions client-side before submission and chunk automatically."],"exampleFix":"// before — 150 actions in one batch\n{ kind: \"batch\", actions: [/* 150 click actions */] }\n// after — two batches of <=100\nawait executeActViaPlaywright({ cdpUrl, action: { kind: \"batch\", actions: first100 } });\nawait executeActViaPlaywright({ cdpUrl, action: { kind: \"batch\", actions: next50 } });","handlingStrategy":"validation","validationCode":"const ACT_MAX_BATCH_ACTIONS = 100;\nfunction chunkBatch<T>(actions: T[], size = ACT_MAX_BATCH_ACTIONS): T[][] {\n  const chunks: T[][] = [];\n  for (let i = 0; i < actions.length; i += size) {\n    chunks.push(actions.slice(i, i + size));\n  }\n  return chunks;\n}\n// Before submitting:\nif (action.actions.length > ACT_MAX_BATCH_ACTIONS) {\n  for (const chunk of chunkBatch(action.actions)) {\n    await executeActViaPlaywright({ cdpUrl, action: { kind: \"batch\", actions: chunk }, evaluateEnabled });\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Chunk large action lists into groups of 100 or fewer before submitting.","Count actions client-side and reject or split oversized batches early.","Combine fine-grained actions (e.g., use fill with multiple fields instead of many type actions)."],"tags":["browser","batch","limit","act"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}