different-ai/openwork · error
Archive is missing .opencode config
Error message
Archive is missing .opencode config
What it means
After extracting all eligible entries from a workspace archive, importWorkspaceConfig verifies that a .opencode directory exists under targetDir. An archive can be a structurally valid ZIP yet contain no .opencode/ files (or only opencode.json), meaning it would not yield a usable OpenWork workspace config, so the import aborts.
Source
Thrown at apps/desktop/electron/workspace-archive.mjs:308
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");
const openworkPath = path.join(opencodeDir, "openwork.json");
let preset = "starter";
let workspaceName = typeof name === "string" && name.trim() ? name.trim() : null;
if (await pathExists(openworkPath)) {
const raw = await readFile(openworkPath, "utf8");
try {
const config = JSON.parse(raw);
config.authorizedRoots = [targetDir];
if (!workspaceName && typeof config.workspace?.name === "string" && config.workspace.name.trim()) {
workspaceName = config.workspace.name.trim();
}
if (typeof config.workspace?.preset === "string" && config.workspace.preset.trim()) {
preset = config.workspace.preset.trim();
}
await writeFile(openworkPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
} catch {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Repack the archive so it contains .opencode/ entries at the archive root (at least one non-secret file under .opencode/).
- Re-export with exportWorkspaceConfig from an existing workspace instead of zipping manually.
- Verify you are importing the right archive and that the zip root is the workspace folder, not its parent.
Example fix
// before: zip -r workspace.zip ./my-project -> entries 'my-project/.opencode/...' // after: run from inside the workspace root zip -r workspace.zip opencode.json .opencode/
Defensive patterns
Strategy: validation
Validate before calling
import { readFile } from "node:fs/promises";
import { listZipEntries } from "./workspace-archive.mjs";
async function archiveHasOpencodeConfig(archivePath) {
const buffer = await readFile(archivePath);
return listZipEntries(buffer).some(
(e) => e.name === "opencode.json" || e.name.startsWith(".opencode/"),
);
} Try / catch
try {
await importWorkspaceConfig({ archivePath, targetDir });
} catch (err) {
if (err.message === "Archive is missing .opencode config") {
// prompt user for a valid workspace archive
} else throw err;
} Prevention
- Zip from inside the workspace root so .opencode/ sits at the archive root.
- Verify the archive lists a .opencode/ entry before importing.
- Prefer exportWorkspaceConfig over manual zipping.
When it happens
Trigger: Calling importWorkspaceConfig with an archive that contains no files under '.opencode/' — e.g. only manifest.json and opencode.json, or an archive of the wrong folder entirely.
Common situations: Hand-built archives zipped from the wrong directory; archives where .opencode entries were skipped because names matched secret-name filters; zipping the parent folder so entries are 'myproject/.opencode/...' with no top-level .opencode files.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Agent context diagnostics timeout must be between 1 ms and 3
- Invalid cloud provider sync response.
- Invalid cloud provider sync status.
- Invalid cloud provider sync status response.
- t("providers.provider_id_required")
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ad74506fccecd51e.
Report an issue: GitHub.