different-ai/openwork · error
Target folder must be empty
Error message
Target folder must be empty
What it means
importWorkspaceConfig extracts an exported archive into targetDir, which must be empty (or nonexistent) to avoid clobbering an existing workspace. If targetDir exists and contains any entries, it throws 'Target folder must be empty'.
Source
Thrown at apps/desktop/electron/workspace-archive.mjs:290
included.push(entry.rel);
}
files.push({
name: "manifest.json",
data: `${JSON.stringify({
version: 1,
createdAtMs: nowMs(),
workspace: { id: workspace.id, name: workspace.name, path: workspace.path },
included,
excluded,
}, null, 2)}\n`,
});
await writeZip(outputPath, files);
return { outputPath, included: included.length, excluded };
}
export async function importWorkspaceConfig({ archivePath, targetDir, name }) {
if (await pathExists(targetDir)) {
if (!(await isDirectoryEmpty(targetDir))) throw new Error("Target folder must be empty");
}
await mkdir(targetDir, { recursive: true });
const archiveStats = await stat(archivePath);
if (archiveStats.size > MAX_ARCHIVE_BYTES) throw new Error("Workspace archive is too large.");
const buffer = await readFile(archivePath);
for (const entry of listZipEntries(buffer)) {
if (entry.name === "manifest.json" || entry.name.endsWith("/")) continue;
if (!isSafeArchivePath(entry.name)) throw new Error("Archive contains an unsafe path");
if (!(entry.name === "opencode.json" || entry.name.startsWith(".opencode/"))) continue;
if (isSecretName(path.basename(entry.name))) continue;
const outPath = path.join(targetDir, ...entry.name.split("/"));
await mkdir(path.dirname(outPath), { recursive: true });
await writeFile(outPath, readZipEntryData(buffer, entry));
}
const opencodeDir = path.join(targetDir, ".opencode");
if (!(await pathExists(opencodeDir))) throw new Error("Archive is missing .opencode config");View on GitHub (pinned to 2b7df46e8a)
Solutions
- Pass a new, empty (or nonexistent) targetDir for the import
- Clear the existing directory (move its contents aside or delete) before importing
- Inspect for leftovers from a previous failed import and clean them up
Example fix
// before
await importWorkspaceConfig({ archivePath: 'ws.zip', targetDir: '/ws/existing' })
// after
await importWorkspaceConfig({ archivePath: 'ws.zip', targetDir: '/ws/existing-import' }) // empty or new Defensive patterns
Strategy: validation
Validate before calling
import { readdir, stat } from 'node:fs/promises';
async function targetIsEmpty(dir) {
try { return (await readdir(dir)).length === 0; }
catch { return true; } // nonexistent counts as empty
} Type guard
function isUsableTarget(dirEmpty) {
return dirEmpty === true;
} Try / catch
try {
await importWorkspaceConfig({ archivePath, targetDir });
} catch (err) {
if (err.message === 'Target folder must be empty') {
// ask user to pick an empty folder or clear the existing one
} else throw err;
} Prevention
- Default the import target to a fresh folder name
- Clean up leftovers from failed imports before retrying
- Never point imports at existing project directories
When it happens
Trigger: Calling importWorkspaceConfig with a targetDir that already exists and is non-empty (readdir returns >= 1 entries).
Common situations: Importing twice into the same folder; choosing an existing project directory as the import target; a previous failed import left partial files behind making the dir non-empty.
Related errors
- Agent context diagnostics timeout must be between 1 ms and 3
- ${result}
- Invalid cloud provider sync response.
- Invalid cloud provider sync status.
- Invalid cloud provider sync status response.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/692787d42e3d2bc0.
Report an issue: GitHub.