paperclipai/paperclip · error
PAPERCLIP_OPENCODE_RUNTIME_DIR is required
Error message
PAPERCLIP_OPENCODE_RUNTIME_DIR is required
What it means
The OpenCode app-server proxy locates its runtime working directory exclusively through the PAPERCLIP_OPENCODE_RUNTIME_DIR environment variable; runtimeDirectory() throws if the variable is unset or only whitespace, because the proxy cannot function without a resolved runtime directory.
Source
Thrown at packages/paperclip-runner/src/cli/opencode-app-server-proxy.ts:81
return new Promise((resolveValue, reject) =>
pending.set(id, { resolve: resolveValue, reject }),
);
}
function record(value: unknown): Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
}
function text(value: unknown, fallback = ""): string {
return typeof value === "string" ? value : fallback;
}
function runtimeDirectory(): string {
const configured = process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR?.trim();
if (!configured)
throw new Error("PAPERCLIP_OPENCODE_RUNTIME_DIR is required");
return resolve(configured);
}
async function open(
params: Record<string, unknown>,
resume: boolean,
): Promise<Record<string, unknown>> {
if (session)
return threadResponse(
session.ids().providerSessionId ?? session.ids().driverSessionId,
);
cwd = resolve(text(params.cwd, process.cwd()));
const model = text(params.model);
if (!model.includes("/"))
throw new Error("OpenCode proxy requires model in provider/model form");
activeModel = model;
const dynamicTools = Array.isArray(params.dynamicTools)
? params.dynamicTools.map(record)View on GitHub (pinned to 01ad858492)
Solutions
- Export PAPERCLIP_OPENCODE_RUNTIME_DIR to the runtime directory path before starting the proxy
- Ensure the supervisor (runnerd) passes its full env to the child process
- Fail fast in the launcher if the var is absent, with a clear message
Example fix
// before
spawn('opencode-app-server-proxy', args);
// after
spawn('opencode-app-server-proxy', args, { env: { ...process.env, PAPERCLIP_OPENCODE_RUNTIME_DIR: runtimeDir } }); Defensive patterns
Strategy: validation
Validate before calling
if (!process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR?.trim()) throw new Error('set PAPERCLIP_OPENCODE_RUNTIME_DIR before starting the proxy'); Type guard
function hasRuntimeDir(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & { PAPERCLIP_OPENCODE_RUNTIME_DIR: string } {
return typeof env.PAPERCLIP_OPENCODE_RUNTIME_DIR === 'string' && env.PAPERCLIP_OPENCODE_RUNTIME_DIR.trim().length > 0;
} Try / catch
try { await proxy.handle(req); }
catch (e) { if (String(e.message).includes('PAPERCLIP_OPENCODE_RUNTIME_DIR is required')) { console.error('Start via runnerd or export PAPERCLIP_OPENCODE_RUNTIME_DIR'); } else throw e; } Prevention
- Launch the proxy only through runnerd, which supplies the env
- In spawn wrappers, always spread the parent env and add required vars
- Add a startup env check with a clear error before any request handling
When it happens
Trigger: Calling open() (directly or via handle) when process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR is missing, empty, or contains only spaces.
Common situations: Launching the proxy outside the runnerd-supervised environment; a spawn wrapper forgetting to forward the parent's env; shell running with a sanitized environment (systemd, cron, CI).
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- database-contract-unmet
- OpenCode evals require exact version 1.18.17; received ${ver
- Unknown config key ${warning.path}; did you mean ${warning.s
- [opencode-local] Remote model availability probe for "${mode
- [opencode-local] Remote `opencode models` returned no models
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/12840d5756efb65e.
Report an issue: GitHub.