paperclipai/paperclip · error
Invalid normalized OpenCode session id
Error message
Invalid normalized OpenCode session id
What it means
Thrown when normalizing a provider session id into a filesystem-safe path segment under the runtime directory produces an empty string, '.', or '..' — i.e. the id is unusable as a directory/file name. This guards against escaping the runtime directory (path traversal) and against empty identifiers.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:2483
"HTTP_PROXY",
"HTTPS_PROXY",
"NO_PROXY",
"ALL_PROXY",
"SSL_CERT_FILE",
"SSL_CERT_DIR",
"OPENROUTER_API_KEY",
];
}
function sessionRoot(
runtimeDirectory: string,
normalizedSessionId: string,
): string {
const safe = normalizedSessionId
.replace(/[^a-zA-Z0-9._-]/g, "_")
.slice(0, 120);
if (!safe || safe === "." || safe === "..")
throw new Error("Invalid normalized OpenCode session id");
return join(resolve(runtimeDirectory), safe);
}
function validateWorkspace(value: string): string {
const cwd = resolve(value);
if (!value.trim() || cwd === dirname(cwd))
throw new Error("OpenCode working directory must not be a filesystem root");
return cwd;
}
function validModel(value: string): boolean {
const slash = value.indexOf("/");
return slash > 0 && slash < value.length - 1;
}
function compareVersion(left: string, right: string): number {
const a = left.split(".").map(Number);
const b = right.split(".").map(Number);View on GitHub (pinned to 01ad858492)
Solutions
- Ensure the provider session id is assigned (from the OpenCode server create-session response) before any code resolves paths from it.
- Log the raw id passed in — if it is empty/undefined, fix the code path that reads the id field (possible API contract drift).
- Treat this as a traversal defense: never bypass the sanitizer; validate the id upstream instead (require /^[a-zA-Z0-9._-]+$/).
- If a placeholder path is needed before the id exists, generate a local uuid rather than passing an empty id.
Example fix
// before
const dir = sessionPath(runtimeDir, providerSessionId ?? "");
// after
if (!providerSessionId || !/^[a-zA-Z0-9._-]+$/.test(providerSessionId)) {
throw new Error("Provider session id not yet assigned");
}
const dir = sessionPath(runtimeDir, providerSessionId); Defensive patterns
Strategy: validation
Validate before calling
if (!providerSessionId || !/^[a-zA-Z0-9._-]+$/.test(providerSessionId)) {
throw new Error("Provider session id missing or unsafe — cannot resolve runtime path");
} Type guard
function isSafeId(v: unknown): v is string {
return typeof v === "string" && /^[a-zA-Z0-9._-]+$/.test(v) && !(v === "." || v === "..");
} Try / catch
try {
const dir = sessionPath(runtimeDir, providerSessionId);
} catch (e) {
if (e instanceof Error && e.message === "Invalid normalized OpenCode session id") {
// id empty/unset — ensure create-session response was processed first
}
} Prevention
- Only resolve runtime paths after the server has assigned a real session id
- Validate ids upstream with a strict allowlist regex instead of relying on sanitization
- Use a local uuid placeholder when a path is needed before the id exists
When it happens
Trigger: normalizedSessionId contains only characters replaced by '_' mapping to '.'/'..' after sanitization, or is empty/whitespace — typically an unset or empty provider session id passed before the server assigned a real id.
Common situations: Calling session-path helpers before the first server response populated #providerSessionId; an upstream API change returning a different id field so undefined/empty is coerced into the sanitizer; ids crafted to collide with '..' for traversal.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Unsafe ${label}: ${result}
- Invalid Discord form token
- sandbox runtime asset key is not a simple path segment: ${ke
- Invalid GitHub launcher run ID
- device-login promotion: the account identifier cannot form a
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/77505d62fbd62691.
Report an issue: GitHub.