Yeachan-Heo/oh-my-codex · error · Error
mode must be a string
Error message
mode must be a string
What it means
validateStateModeSegment throws when the mode argument is not a string. Mode segments are embedded into state filenames, so the type is enforced before any pattern check.
Source
Thrown at src/mcp/state-paths.ts:132
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 ".."');
}
if (normalized.includes('/') || normalized.includes('\\')) {
throw new Error('mode must not contain path separators');
}
if (!STATE_MODE_SEGMENT_PATTERN.test(normalized)) {
throw new Error('mode must match ^[A-Za-z0-9_-]{1,64}$');
}
return normalized;
}
export function getStateFilename(mode: string): string {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Coerce to string at the boundary: String(mode) or template literal
- Default the mode explicitly, e.g. mode ?? "default"
- Type the config schema so mode must be a string
Example fix
// before getStateFilename(42); // after getStateFilename(String(42)); // "42.json"
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof mode !== 'string') mode = String(mode);
Type guard
function isModeString(v: unknown): v is string { return typeof v === 'string'; } Prevention
- Type mode as string in config schemas
- Default mode: mode ?? 'default'
When it happens
Trigger: Passing mode: 123, mode: null-as-value, or an array/object from untyped JSON. (undefined is not special-cased here — typeof check throws for anything non-string.)
Common situations: Config parsed from YAML where a bare mode: 42 becomes a number; defaulted mode left undefined; forwarding query params without coercion.
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
- fileName must be a string
- ${name} must be a string
- session_id must be a string
- mode must be a non-empty string
- mode must not contain ".."
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/89e6edc07ee6166d.
Report an issue: GitHub.