{"record":{"id":"dc29bb351a5d3f40","repo":"Yeachan-Heo/oh-my-codex","slug":"filename-must-be-a-string","errorCode":null,"errorMessage":"fileName must be a string","messagePattern":"fileName must be a string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mcp/state-paths.ts","lineNumber":156,"sourceCode":"  if (normalized.includes('..')) {\n    throw new Error('mode must not contain \"..\"');\n  }\n  if (normalized.includes('/') || normalized.includes('\\\\')) {\n    throw new Error('mode must not contain path separators');\n  }\n  if (!STATE_MODE_SEGMENT_PATTERN.test(normalized)) {\n    throw new Error('mode must match ^[A-Za-z0-9_-]{1,64}$');\n  }\n  return normalized;\n}\n\nexport function getStateFilename(mode: string): string {\n  return `${validateStateModeSegment(mode)}${STATE_FILE_SUFFIX}`;\n}\n\nexport function validateStateFileName(fileName: unknown): string {\n  if (typeof fileName !== 'string') {\n    throw new Error('fileName must be a string');\n  }\n  const normalized = fileName.trim();\n  if (!normalized) {\n    throw new Error('fileName must be a non-empty string');\n  }\n  if (normalized.includes('..')) {\n    throw new Error('fileName must not contain \"..\"');\n  }\n  if (normalized.includes('/') || normalized.includes('\\\\')) {\n    throw new Error('fileName must not contain path separators');\n  }\n  if (!STATE_FILE_NAME_PATTERN.test(normalized)) {\n    throw new Error('fileName must match ^[A-Za-z0-9._-]{1,128}$');\n  }\n  return normalized;\n}\n\nfunction convertWindowsToWslPath(raw: string): string {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/mcp/state-paths.ts#L138-L174","documentation":"validateStateFileName throws when the fileName argument is not a string. FileNames are user-facing state file identifiers joined into state directory paths, so type is checked before any content validation.","triggerScenarios":"fileName: 123, fileName: true, fileName: [\"state.json\"], or undefined passed explicitly.","commonSituations":"Untyped JSON config; programmatic callers passing Path objects or file handles; destructuring mistakes leaving fileName undefined.","solutions":["Coerce with String(fileName) at the call site","Default it: fileName ?? defaultStateFileName","Add a runtime type guard in your client wrapper"],"exampleFix":"// before\ngetStateFilePath(123);\n// after\ngetStateFilePath(String(123));","handlingStrategy":"type-guard","validationCode":"if (typeof fileName !== 'string') fileName = String(fileName);","typeGuard":"function isFileNameInput(v: unknown): v is string { return typeof v === 'string'; }","tryCatchPattern":null,"preventionTips":["Convert Path objects/numbers with String() at the boundary","Default fileName when optional"],"tags":["type-validation","state","mcp"],"backgroundTag":"wrong-argument-type","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}