firecrawl/open-lovable · error · Error
Unsupported sandbox type
Error message
Unsupported sandbox type
What it means
Thrown by the apply-ai-code route when the connected sandbox object exposes neither the V2 provider interface (`writeFile` on the sandbox) nor the V1 E2B direct interface (`sandbox.files.write`). It signals that the sandbox SDK instance in `global.activeSandbox` does not match any file-writing API shape the route knows how to use, so files from generated AI code cannot be persisted.
Source
Thrown at app/api/apply-ai-code/route.ts:454
// Replace shadow-3xl with shadow-2xl (shadow-3xl doesn't exist)
fileContent = fileContent.replace(/shadow-3xl/g, 'shadow-2xl');
// Replace any other non-existent shadow utilities
fileContent = fileContent.replace(/shadow-4xl/g, 'shadow-2xl');
fileContent = fileContent.replace(/shadow-5xl/g, 'shadow-2xl');
}
console.log(`[apply-ai-code] Writing file using E2B files API: ${fullPath}`);
try {
// Check if we're using provider pattern (v2) or direct sandbox (v1)
if (sandbox.writeFile) {
// V2: Provider pattern (Vercel/E2B provider)
await sandbox.writeFile(file.path, fileContent);
} else if (sandbox.files?.write) {
// V1: Direct E2B sandbox
await sandbox.files.write(fullPath, fileContent);
} else {
throw new Error('Unsupported sandbox type');
}
console.log(`[apply-ai-code] Successfully wrote file: ${fullPath}`);
// Update file cache
if (global.sandboxState?.fileCache) {
global.sandboxState.fileCache.files[normalizedPath] = {
content: fileContent,
lastModified: Date.now()
};
console.log(`[apply-ai-code] Updated file cache for: ${normalizedPath}`);
}
} catch (writeError) {
console.error(`[apply-ai-code] E2B file write error:`, writeError);
throw writeError as Error;
}
View on GitHub (pinned to 69bd93bae7)
Solutions
- Log `Object.keys(global.activeSandbox)` (and of `files`) at the start of the route to confirm which API shape the sandbox actually has
- Pin/align the sandbox SDK version so the app's V1 or V2 code path matches the installed package
- Add the missing branch for the provider in use (e.g. call the provider's own write helper) before the throw
- Ensure the sandbox is created through the same factory the rest of the app uses, then re-create it and retry
Example fix
// before
} else if (sandbox.files?.write) {
await sandbox.files.write(fullPath, fileContent);
} else {
throw new Error('Unsupported sandbox type');
}
// after
} else if (sandbox.files?.write) {
await sandbox.files.write(fullPath, fileContent);
} else if (typeof sandbox.writeFile === 'function') {
await sandbox.writeFile(file.path, fileContent);
} else if (typeof sandbox.fs?.writeFile === 'function') {
await sandbox.fs.writeFile(fullPath, fileContent);
} else {
throw new Error(`Unsupported sandbox type: ${sandbox?.constructor?.name}`);
} Defensive patterns
Strategy: validation
Validate before calling
function canWriteFiles(sandbox) {
return Boolean(sandbox) && (typeof sandbox.writeFile === 'function' || Boolean(sandbox.files?.write));
}
if (!canWriteFiles(global.activeSandbox)) throw new Error('Sandbox does not support file writes; recreate it'); Type guard
function isWritableSandbox(s: any): s is { writeFile?: (p: string, c: string) => Promise<unknown>; files?: { write: (p: string, c: string) => Promise<unknown> } } {
return typeof s?.writeFile === 'function' || typeof s?.files?.write === 'function';
} Try / catch
try {
await applyAiCode(files);
} catch (e) {
if (e.message === 'Unsupported sandbox type') {
await recreateSandbox();
return applyAiCode(files); // retry once with a fresh sandbox
}
throw e;
} Prevention
- Create sandboxes only via the app's single factory so the API shape is guaranteed
- Log Object.keys(sandbox) once at creation to detect SDK shape drift after upgrades
- Pin sandbox SDK versions in package.json and test apply-ai-code after any bump
- Add a startup smoke test that writes a temp file through the chosen API path
When it happens
Trigger: POST /api/apply-ai-code with an activeSandbox that was created by a different SDK version (e.g. a plain object, a Daytona or other provider sandbox without `writeFile`, or an E2B beta SDK where `files` is undefined), or activeSandbox being set to a stale/partially-initialized object.
Common situations: Upgrading or downgrading the `e2b` / `e2b-Code-interpreter` packages so the API surface changed; mixing providers (Vercel sandbox vs E2B) so neither branch matches; a hot-reload wiping the real sandbox but leaving a stale global reference.
Related errors
- No active sandbox
- Failed to create zip: ${error}
- Failed to read zip file: ${error}
- Failed to list files
- Unable to read file: ${normalizedPath}
AI-assisted analysis of firecrawl/open-lovable@69bd93bae7 (2026-08-28).
Data as JSON: /api/errors/efeede6cb9244988.
Report an issue: GitHub.