{"record":{"id":"932c5a6a33ab617e","repo":"Yeachan-Heo/oh-my-codex","slug":"filename-must-be-a-non-empty-string","errorCode":null,"errorMessage":"fileName must be a non-empty string","messagePattern":"fileName must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mcp/state-paths.ts","lineNumber":160,"sourceCode":"    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 {\n  const m = /^([a-zA-Z]):[\\\\/](.*)$/.exec(raw);\n  if (!m) return raw;\n  const drive = m[1].toLowerCase();\n  const rest = String(m[2] || '').replace(/\\\\/g, '/');","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/mcp/state-paths.ts#L142-L178","documentation":"Thrown when fileName trims to an empty string. An empty filename would resolve to the state directory itself rather than a file, so it is rejected.","triggerScenarios":"fileName: \"\", fileName: \"  \", or a whitespace-only value from trimmed form input.","commonSituations":"Optional fileName field defaulted to \"\" instead of undefined; template strings producing empty output; copy-paste of blank cells from spreadsheets.","solutions":["Omit the fileName when empty rather than passing \"\"","Default to a concrete name like \"state.json\"","Validate with .trim() at config load"],"exampleFix":"// before\ngetStateFilePath(\"   \");\n// after\ngetStateFilePath(\"state.json\");","handlingStrategy":"validation","validationCode":"fileName = fileName?.trim() || 'state.json';","typeGuard":"function isNonEmptyFileName(v: string): boolean { return v.trim().length > 0; }","tryCatchPattern":null,"preventionTips":["Use undefined for absent, never empty string","Default blank inputs to a concrete filename"],"tags":["validation","state","mcp"],"backgroundTag":"empty-string-argument","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}