openai/codex-plugin-cc · error · Error

Claude session source must be a JSONL file: ${sourcePath}

Error message

Claude session source must be a JSONL file: ${sourcePath}

What it means

Thrown by resolveClaudeSessionPath when the resolved source path does not have a '.jsonl' extension. Claude transcripts on disk are newline-delimited JSON (.jsonl); any other extension indicates the wrong file was supplied and would fail to parse.

Source

Thrown at plugins/codex/scripts/lib/claude-session-transfer.mjs:28

function resolveUserPath(cwd, value) {
  if (value === "~") {
    return os.homedir();
  }
  if (String(value).startsWith("~/")) {
    return path.join(os.homedir(), String(value).slice(2));
  }
  return ensureAbsolutePath(cwd, value);
}

export function resolveClaudeSessionPath(cwd, options = {}) {
  const requestedPath = options.source || process.env[TRANSCRIPT_PATH_ENV];
  if (!requestedPath) {
    throw new Error("Could not identify the current Claude transcript. Retry with --source <path-to-claude-jsonl>.");
  }

  const sourcePath = resolveUserPath(cwd, requestedPath);
  if (path.extname(sourcePath) !== ".jsonl") {
    throw new Error(`Claude session source must be a JSONL file: ${sourcePath}`);
  }

  let source;
  let projects;
  try {
    source = fs.realpathSync(sourcePath);
    projects = fs.realpathSync(CLAUDE_PROJECTS_DIR);
  } catch {
    throw new Error(`Claude session file not found: ${sourcePath}`);
  }
  const relative = path.relative(projects, source);
  if (relative === "" || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
    throw new Error(`Codex can import Claude sessions only from ${CLAUDE_PROJECTS_DIR}: ${source}`);
  }
  return source;
}

View on GitHub (pinned to db52e28f4d)

Solutions

  1. Point --source at the actual Claude '.jsonl' transcript file.
  2. If you only have a .json export, convert/re-export it to JSONL first.
  3. Confirm path.extname(source) === '.jsonl' before calling.
  4. Avoid passing directories; resolve to the specific transcript file.

Example fix

// before
resolveClaudeSessionPath(cwd, { source: '~/session.json' }) // throws

// after
resolveClaudeSessionPath(cwd, { source: '~/.claude/projects/-home-user-proj/session.jsonl' })
Defensive patterns

Strategy: validation

Validate before calling

import path from 'node:path';
function assertJsonl(p) {
  if (path.extname(p) !== '.jsonl') {
    throw new Error(`Expected a .jsonl transcript, got: ${p}`);
  }
}
// call before resolveClaudeSessionPath:
//   assertJsonl(options.source);

Type guard

function isJsonlPath(p) {
  return typeof p === 'string' && p.toLowerCase().endsWith('.jsonl');
}

Try / catch

null

Prevention

When it happens

Trigger: Calling resolveClaudeSessionPath with options.source pointing to a '.json', '.txt', '.log', extensionless file, or a directory. Example: { source: 'session.json' } or { source: '~/transcript.txt' }.

Common situations: User selects a pretty-printed '.json' export instead of the raw '.jsonl' stream. A glob matched the wrong file. The user mistyped the extension or passed a directory.

Related errors


AI-assisted analysis of openai/codex-plugin-cc@db52e28f4d (2026-08-13). Data as JSON: /api/errors/69e9d03efb261b7b. Report an issue: GitHub.