paperclipai/paperclip · error
Managed OpenCode authentication requires an isolated remote…
Error message
Managed OpenCode authentication requires an isolated remote runtime directory.
What it means
When a managed AI connection is configured for OpenCode, the runtime must isolate HOME/XDG directories per run under a remote runtime root so credentials never collide or leak between runs. If the runtime root directory is not provided (null/undefined), the setup function refuses to build a managed-auth home and throws. This protects the managed authentication model: without isolation, OpenCode would use the ambient HOME.
Solutions
- Provision and pass runtimeRootDir when constructing the adapter execution environment.
- Only enable config.managedAiConnection on runtimes that supply an isolated remote runtime directory.
- Check the caller (execute/testEnvironment) wiring so runtimeRootDir is derived before managed-auth setup runs.
Example fix
// before
await adapter.testEnvironment({ config: { managedAiConnection } });
// after
await adapter.testEnvironment({ config: { managedAiConnection }, runtimeRootDir }); Defensive patterns
Strategy: validation
Validate before calling
if (config.managedAiConnection && !runtimeRootDir) throw new Error("managed OpenCode auth needs runtimeRootDir"); Type guard
const canPrepareManagedAuth = (i: { config: { managedAiConnection?: unknown }; runtimeRootDir?: string | null }): i is typeof i & { runtimeRootDir: string } =>
!i.config.managedAiConnection || (typeof i.runtimeRootDir === "string" && i.runtimeRootDir.length > 0); Try / catch
try { await prepareManagedOpenCodeRemoteHomes(input); } catch (e) {
if (e.message.includes("isolated remote runtime directory")) { console.error("provide runtimeRootDir or disable managedAiConnection"); }
throw e;
} Prevention
- Always provision runtimeRootDir before adapter execute/testEnvironment
- Only enable managedAiConnection on runtimes with remote isolation support
- Add an assertion at call sites that pass managedAiConnection
- Keep managed-auth wiring tests covering the missing-runtimeRootDir case
When it happens
Trigger: prepareManagedOpenCodeRemoteHomes (via execute or testEnvironment) receives input.config.managedAiConnection set but input.runtimeRootDir null or undefined.
Common situations: Calling the adapter's execute/testEnvironment without provisioning the sandbox runtime root; a refactor stopped passing runtimeRootDir; running managed-auth mode on a runtime type that does not supply a remote root (local vs remote mismatch).
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- PAPERCLIP_OPENCODE_RUNTIME_DIR is required
- A different semantic result was already committed
- ACPX profile requires exact model ; received
- ACPX model must not be empty
- ACPX provider identity contains an invalid permission mode
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/98309bbb12536573.
Report an issue: GitHub.
Appendix: source
Thrown at packages/adapters/opencode-local/src/server/runtime-config.ts:253
XDG_CONFIG_HOME: runtimeConfigHome,
},
notes,
cleanup: async () => {
await fs.rm(runtimeConfigHome, { recursive: true, force: true });
},
};
}
/** Managed credentials must never leave host-only homes in a remote process. */
export function prepareManagedOpenCodeRemoteHomes(input: {
env: Record<string, string>;
config: Record<string, unknown>;
runtimeRootDir: string | null | undefined;
runId: string;
configDir?: string;
}): void {
if (!input.config.managedAiConnection) return;
if (!input.runtimeRootDir) throw new Error("Managed OpenCode authentication requires an isolated remote runtime directory.");
const home = path.posix.join(input.runtimeRootDir, "managed-auth", input.runId);
Object.assign(input.env, {
HOME: home,
XDG_CONFIG_HOME: input.configDir ?? path.posix.join(home, "config"),
XDG_DATA_HOME: path.posix.join(home, "data"),
XDG_CACHE_HOME: path.posix.join(home, "cache"),
XDG_STATE_HOME: path.posix.join(home, "state"),
});
}
View on GitHub (pinned to 3f1d897a7c)