{"record":{"id":"cedb3b62ba2317f1","repo":"vercel/ai","slug":"invalid-argument-for-parameter-batch-batch-must-b","errorCode":null,"errorMessage":"Invalid argument for parameter batch: batch must be a supported text batch reference","messagePattern":"Invalid argument for parameter batch: batch must be a supported text batch reference","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/batch/batch.ts","lineNumber":284,"sourceCode":"        parameter: 'requests',\n        value: requests,\n        message: `request IDs must be unique; duplicate ID \"${request.id}\"`,\n      });\n    }\n\n    ids.add(request.id);\n  }\n}\n\nfunction validateBatchReference({\n  model,\n  batch,\n}: {\n  model: BatchLanguageModelV4;\n  batch: BatchReference;\n}) {\n  if (batch.version !== 1 || batch.type !== 'text') {\n    throw new InvalidArgumentError({\n      parameter: 'batch',\n      value: batch,\n      message: 'batch must be a supported text batch reference',\n    });\n  }\n\n  if (batch.provider !== model.provider || batch.modelId !== model.modelId) {\n    throw new InvalidArgumentError({\n      parameter: 'model',\n      value: model,\n      message:\n        `model ${model.provider}:${model.modelId} is not compatible with ` +\n        `batch ${batch.provider}:${batch.modelId}`,\n    });\n  }\n}\n\nasync function convertBatchItemResult(","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/ai/src/batch/batch.ts#L266-L302","documentation":"When lifecycle state records a bridge sandboxId, validateACPLifecycleCompatibility verifies it matches the sandboxId of the session being created. A mismatch means the state belongs to a different sandbox (machine/container) than the one this harness is attached to, so resume is rejected to avoid operating on the wrong sandbox.","triggerScenarios":"Calling createACPV1 with a sandbox session whose id differs from lifecycleData.bridge.sandboxId; reattaching lifecycle state to a newly created sandbox; pointing the harness at a different sandbox environment after the original one expired or was replaced.","commonSituations":"A sandbox was restarted or recreated (new sandbox id) while the old lifecycle state was kept; connecting to a teammate's or another environment's sandbox; reusing saved state across dev/staging sandboxes.","solutions":["Attach to the sandbox whose id matches lifecycleData.bridge.sandboxId.","If the original sandbox is gone, start a fresh session instead of resuming the state.","Copy/persist state per sandbox and key it by sandboxId to avoid cross-sandbox reuse."],"exampleFix":"// before\ncreateACPV1({ sandbox: sandboxNew, lifecycle: stateFromSandboxOld })\n\n// after\nconst sandbox = await connectToSandbox({ id: state.bridge.sandboxId });\ncreateACPV1({ sandbox, lifecycle: stateFromSandboxOld })","handlingStrategy":"validation","validationCode":"const expected = lifecycleData.bridge?.sandboxId;\nif (expected != null && sandbox.id != null && expected !== sandbox.id) {\n  throw new Error(`Lifecycle state belongs to sandbox ${expected}, not ${sandbox.id}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  harness = createACPV1({ sandbox, lifecycle: state });\n} catch (error) {\n  if (error instanceof Error && error.message.includes('belongs to sandbox')) {\n    // original sandbox is gone or different: start a fresh session\n    harness = createACPV1({ sandbox });\n  } else {\n    throw error;\n  }\n}","preventionTips":["Persist lifecycle state per sandboxId and look it up by the sandbox you attach to.","Detect sandbox recreation (new id) and invalidate saved lifecycle state.","Avoid sharing session state between dev/staging/prod sandboxes."],"tags":["acp","lifecycle","sandbox","identity-mismatch"],"backgroundTag":"sandbox-id-mismatch","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}