vercel/ai · error · Error
prepareSandboxForHarness: at least one harness must be provi
Error message
prepareSandboxForHarness: at least one harness must be provided.
What it means
prepareSandboxForHarness exists to pre-warm a sandbox for one or more harnesses; calling it with an empty harnesses array would be a no-op with misleading success semantics, so it throws. At least one harness entry is required.
Source
Thrown at packages/harness/src/agent/prepare-sandbox-for-harness.ts:53
* committing, snapshotting, or otherwise persisting that modified filesystem.
* When a later `HarnessAgent` session uses a sandbox created from the persisted
* artifact, the adapter recomputes the same recipe identity and the existing
* bootstrap marker makes the bootstrap logic a no-op.
*
* Repeated harness IDs are prepared once. When multiple adapters use the same
* ID, the last adapter in `harnesses` is used.
*/
export async function prepareSandboxForHarness(options: {
readonly session: SandboxSession;
readonly harnesses: ReadonlyArray<HarnessAgentAdapter>;
readonly sandboxConfig?: HarnessAgentSandboxConfig;
readonly abortSignal?: AbortSignal;
}): Promise<PrepareSandboxForHarnessResult> {
const sandboxConfig = options.sandboxConfig ?? {};
validateSandboxBootstrapSettings(sandboxConfig);
if (options.harnesses.length === 0) {
throw new Error(
'prepareSandboxForHarness: at least one harness must be provided.',
);
}
const harnesses = [
...new Map(
options.harnesses.map(harness => [harness.harnessId, harness]),
).values(),
].sort((a, b) => a.harnessId.localeCompare(b.harnessId));
const workDir =
sandboxConfig.workDir == null
? undefined
: normalizeSandboxWorkDir(sandboxConfig.workDir);
const recipeIdentities: Record<string, string> = {};
const skippedHarnessIds: string[] = [];
let defaultWorkingDirectory: string | undefined;
View on GitHub (pinned to 69428b1f8b)
Solutions
- Pass at least one harness in the harnesses array.
- Guard the call: only invoke prepareSandboxForHarness when harnesses.length > 0.
- Fix the logic that builds the harnesses list so it isn't empty.
Example fix
// before
await prepareSandboxForHarness({ harnesses: [], sandboxConfig });
// after
if (harnesses.length > 0) {
await prepareSandboxForHarness({ harnesses, sandboxConfig });
} Defensive patterns
Strategy: validation
Validate before calling
if (!harnesses || harnesses.length === 0) return; // or throw early with context
Try / catch
try { await prepareSandboxForHarness({ harnesses, sandboxConfig }); } catch (e) { if (e.message.includes('at least one harness')) { /* skip pre-warm or build harnesses */ } else throw e; } Prevention
- Guard optional pre-warm calls with harnesses.length > 0
- Avoid building harness lists from all-optional flags without an emptiness check
- Log when the harness list ends up empty to surface config bugs
When it happens
Trigger: Calling prepareSandboxForHarness({ harnesses: [] }) — e.g. when the harness list is built conditionally and every condition was false.
Common situations: Dynamically collecting harnesses from feature flags that are all disabled; filtering the harness array before the call and accidentally emptying it.
Related errors
- The Claude Code harness requires an explicit `portEndpoint`
- 'HarnessAgent: `sandboxConfig.workDir` must not contain NUL.
- 'HarnessAgent: `sandboxConfig.workDir` must be relative.'
- Invalid argument for parameter output: Invalid output type.
- Continuation maxAgeMs must be a positive integer.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/a4ebb35c7ad4c79c.
Report an issue: GitHub.