Yeachan-Heo/oh-my-codex · error · Error

fileName must not contain path separators

Error message

fileName must not contain path separators

What it means

Thrown when fileName contains a / or \\ separator. fileName must be a bare file name, not a path — separators would create or reference subdirectories inside/around the state directory.

Source

Thrown at src/mcp/state-paths.ts:166

}

export function getStateFilename(mode: string): string {
  return `${validateStateModeSegment(mode)}${STATE_FILE_SUFFIX}`;
}

export function validateStateFileName(fileName: unknown): string {
  if (typeof fileName !== 'string') {
    throw new Error('fileName must be a string');
  }
  const normalized = fileName.trim();
  if (!normalized) {
    throw new Error('fileName must be a non-empty string');
  }
  if (normalized.includes('..')) {
    throw new Error('fileName must not contain ".."');
  }
  if (normalized.includes('/') || normalized.includes('\\')) {
    throw new Error('fileName must not contain path separators');
  }
  if (!STATE_FILE_NAME_PATTERN.test(normalized)) {
    throw new Error('fileName must match ^[A-Za-z0-9._-]{1,128}$');
  }
  return normalized;
}

function convertWindowsToWslPath(raw: string): string {
  const m = /^([a-zA-Z]):[\\/](.*)$/.exec(raw);
  if (!m) return raw;
  const drive = m[1].toLowerCase();
  const rest = String(m[2] || '').replace(/\\/g, '/');
  const mountRoot = `/mnt/${drive}`;
  if (!existsSync(mountRoot)) return raw;
  return rest ? `${mountRoot}/${rest}` : mountRoot;
}

function convertWslToWindowsPath(raw: string): string {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Pass only the basename: path.basename(fullPath)
  2. Normalize separators to hyphens if you need hierarchy encoded: p.split(/[\\/]/).join("-")
  3. Keep fileName a flat slug

Example fix

// before
getStateFilePath("team/state.json");
// after
getStateFilePath(path.basename("team/state.json")); // "state.json"
Defensive patterns

Strategy: validation

Validate before calling

import { basename } from 'node:path';
fileName = basename(fileName.replace(/\\/g, '/'));

Type guard

function isBareFileName(v: string): boolean { return !/[\\/]/.test(v); }

Prevention

When it happens

Trigger: fileName: "sub/state.json", fileName: "logs\\state.json", or passing a full path like "/etc/x" (also fails the earlier checks).

Common situations: Passing path.join(...) output where a basename is expected; Windows clients using backslashes; directory structure encoded into the name.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/b58bb53f4ca66839. Report an issue: GitHub.