Yeachan-Heo/oh-my-codex · error · Error
session_id must be a string
Error message
session_id must be a string
What it means
validateSessionId in state-paths throws when session_id is provided but is not a string (number, object, array, boolean). Session IDs are used to build state directory names, so they must be strings matching a strict pattern.
Source
Thrown at src/mcp/state-paths.ts:121
export type StateFileScope = 'root' | 'session';
export interface ModeStateFileRef {
mode: string;
path: string;
scope: StateFileScope;
}
export function normalizeSessionId(sessionId: unknown): string | undefined {
if (typeof sessionId !== 'string') return undefined;
const normalized = sessionId.trim();
return SESSION_ID_PATTERN.test(normalized) ? normalized : undefined;
}
export function validateSessionId(sessionId: unknown): string | undefined {
if (sessionId == null) return undefined;
if (typeof sessionId !== 'string') {
throw new Error('session_id must be a string');
}
if (!SESSION_ID_PATTERN.test(sessionId)) {
throw new Error('session_id must match ^[A-Za-z0-9_-]{1,64}$');
}
return sessionId;
}
export function validateStateModeSegment(mode: unknown): string {
if (typeof mode !== 'string') {
throw new Error('mode must be a string');
}
const normalized = mode.trim();
if (!normalized) {
throw new Error('mode must be a non-empty string');
}
if (normalized.includes('..')) {
throw new Error('mode must not contain ".."');View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Convert the ID to a string before calling: String(sessionId)
- Fix the producer so session_id is serialized as a JSON string
- Add a type guard on the boundary of your client code
Example fix
// before validateSessionId(12345); // after validateSessionId(String(12345)); // "12345"
Defensive patterns
Strategy: type-guard
Validate before calling
if (sessionId != null && typeof sessionId !== 'string') sessionId = String(sessionId);
Type guard
function isSessionIdInput(v: unknown): v is string | undefined | null { return v == null || typeof v === 'string'; } Try / catch
try { validateSessionId(id); } catch (e) { if ((e as Error).message === 'session_id must be a string') id = String(id); else throw e; } Prevention
- Coerce IDs to strings where they originate (DB, URL params)
- Stringify numeric IDs at the JSON boundary
When it happens
Trigger: Passing session_id: 12345 (number from a JSON producer that dropped quotes), session_id: {id: "x"}, or an array. null/undefined is allowed and returns undefined; any other non-string type throws.
Common situations: JSON serialization losing string quoting for numeric-looking IDs; forwarding IDs from a database as numbers; LLM tool calls emitting numbers for IDs.
Understand the failure class
Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.
Related errors
- ${name} must be a string
- session_id must match ^[A-Za-z0-9_-]{1,64}$
- mode must be a string
- fileName must be a string
- autoresearch candidate artifact candidate_commit must be str
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/c98a59ba28bc6373.
Report an issue: GitHub.