vercel/ai · error · InvalidArgumentError

Invalid argument for parameter batch: batch must be a suppor

Error message

Invalid argument for parameter batch: batch must be a supported text batch reference

What it means

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.

Source

Thrown at packages/ai/src/batch/batch.ts:284

        parameter: 'requests',
        value: requests,
        message: `request IDs must be unique; duplicate ID "${request.id}"`,
      });
    }

    ids.add(request.id);
  }
}

function validateBatchReference({
  model,
  batch,
}: {
  model: BatchLanguageModelV4;
  batch: BatchReference;
}) {
  if (batch.version !== 1 || batch.type !== 'text') {
    throw new InvalidArgumentError({
      parameter: 'batch',
      value: batch,
      message: 'batch must be a supported text batch reference',
    });
  }

  if (batch.provider !== model.provider || batch.modelId !== model.modelId) {
    throw new InvalidArgumentError({
      parameter: 'model',
      value: model,
      message:
        `model ${model.provider}:${model.modelId} is not compatible with ` +
        `batch ${batch.provider}:${batch.modelId}`,
    });
  }
}

async function convertBatchItemResult(

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Attach to the sandbox whose id matches lifecycleData.bridge.sandboxId.
  2. If the original sandbox is gone, start a fresh session instead of resuming the state.
  3. Copy/persist state per sandbox and key it by sandboxId to avoid cross-sandbox reuse.

Example fix

// before
createACPV1({ sandbox: sandboxNew, lifecycle: stateFromSandboxOld })

// after
const sandbox = await connectToSandbox({ id: state.bridge.sandboxId });
createACPV1({ sandbox, lifecycle: stateFromSandboxOld })
Defensive patterns

Strategy: validation

Validate before calling

const expected = lifecycleData.bridge?.sandboxId;
if (expected != null && sandbox.id != null && expected !== sandbox.id) {
  throw new Error(`Lifecycle state belongs to sandbox ${expected}, not ${sandbox.id}`);
}

Try / catch

try {
  harness = createACPV1({ sandbox, lifecycle: state });
} catch (error) {
  if (error instanceof Error && error.message.includes('belongs to sandbox')) {
    // original sandbox is gone or different: start a fresh session
    harness = createACPV1({ sandbox });
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/cedb3b62ba2317f1. Report an issue: GitHub.