Yeachan-Heo/oh-my-codex · error · Error
invalid detached leader payload
Error message
invalid detached leader payload
What it means
decodeDetachedLeaderPayload validates the base64url-encoded leader payload passed to the detached leader. The first throw rejects payloads that are empty or contain characters outside the base64url alphabet [A-Za-z0-9_-] before any decoding is attempted.
Source
Thrown at src/cli/index.ts:6947
}
interface DetachedLeaderPayload {
cwd: string;
sessionName: string;
sessionId: string;
codexCmd: string;
codexHomeOverride?: string;
projectLocalCodexHomeForCleanup?: string;
runtimeCodexHomeForCleanup?: string;
parentEnv?: Record<string, string>;
readyPath?: string;
preLaunchOptions: DetachedLeaderPreLaunchOptions;
}
export function decodeDetachedLeaderPayload(encoded: string | undefined): DetachedLeaderPayload {
if (!encoded || !/^[A-Za-z0-9_-]+$/.test(encoded)) throw new Error("invalid detached leader payload");
let value: unknown;
try { value = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8")); } catch { throw new Error("invalid detached leader payload"); }
if (!value || typeof value !== "object") throw new Error("invalid detached leader payload");
const payload = value as Record<string, unknown>;
const options = payload.preLaunchOptions;
if (typeof payload.cwd !== "string" || typeof payload.sessionName !== "string" || typeof payload.sessionId !== "string" ||
typeof payload.codexCmd !== "string" || !options || typeof options !== "object" ||
typeof (options as Record<string, unknown>).enableNotifyFallbackAuthority !== "boolean" ||
typeof (options as Record<string, unknown>).worktreeDirty !== "boolean" ||
typeof (options as Record<string, unknown>).shouldAttach !== "boolean") throw new Error("invalid detached leader payload");
const notifyTempContract = (options as Record<string, unknown>).notifyTempContract;
if (notifyTempContract !== undefined && (!notifyTempContract || typeof notifyTempContract !== "object")) throw new Error("invalid detached leader payload");
const parentEnv = payload.parentEnv;
if (parentEnv !== undefined && (!parentEnv || typeof parentEnv !== "object" ||
Object.entries(parentEnv).some(([key, value]) => !SHELL_ENV_NAME_PATTERN.test(key) || DETACHED_SESSION_PANE_ENV_KEYS.has(key) || typeof value !== "string" || value.includes("\0")))) {
throw new Error("invalid detached leader parent environment");
}
return {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Encode with base64url, not standard base64: Buffer.from(JSON.stringify(p)).toString('base64url')
- Pass the payload as a single quoted argv/env value to avoid shell mangling or truncation
- Prefer letting OMX construct and pass the payload itself rather than building it manually
- Validate length and charset before invoking if generating payloads programmatically
Example fix
// before
const encoded = Buffer.from(json).toString("base64"); // may include + and =
// after
const encoded = Buffer.from(json).toString("base64url"); Defensive patterns
Strategy: type-guard
Validate before calling
function isBase64Url(s: string): boolean { return /^[A-Za-z0-9_-]+$/.test(s); }
if (!payload || !isBase64Url(payload)) throw new TypeError("payload must be base64url without padding"); Type guard
function isBase64UrlPayload(s: unknown): s is string { return typeof s === "string" && s.length > 0 && /^[A-Za-z0-9_-]+$/.test(s); } Try / catch
try { decodeDetachedLeaderPayload(encoded); } catch (e) { if (e.message === "invalid detached leader payload") { /* re-encode with base64url and retry */ } } Prevention
- Always encode with Buffer.toString('base64url'), never 'base64'
- Pass payloads as a single quoted argv or env value
- Round-trip-test generated payloads before shipping them
When it happens
Trigger: The encoded payload argument is undefined/empty, or was mangled in transit — shell quoting stripping characters, a non-base64url string passed by a wrapper, truncation through env var or argv length limits, or manual construction of the payload with padding '+'/'=' characters (standard base64 instead of base64url).
Common situations: Manually invoking the detached leader subcommand with a hand-encoded payload; scripts that pipe the payload through shells that mangle it; using standard base64 (with +/=) instead of base64url encoding.
Related errors
- invalid auth slot path
- Autoresearch goal ${mission.slug} cannot complete until prof
- autoresearch candidate artifact notes must be a string array
- autoresearch candidate artifact created_at is required
- catalog_manifest_invalid:${field}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/f85d9f45d8b92b68.
Report an issue: GitHub.