vercel/ai · error · Error

Invalid Cline history file name: ${input.historyFileName}

Error message

Invalid Cline history file name: ${input.historyFileName}

What it means

resolveContainedSandboxPath validates that a Cline history file name resolves to a file inside the history directory. It computes path.posix.relative(historyDir, filePath) and throws if the result is empty (points at the directory itself), starts with '..' (escapes the directory), or is absolute. This prevents path-traversal or out-of-sandbox access when reading Cline resume history.

Source

Thrown at packages/harness-cline/src/cline-resume-state.ts:83

  return privateSessionDir;
}

function resolveContainedSandboxPath(input: {
  readonly privateSessionDir: string;
  readonly historyFileName: string;
}): string {
  const historyDir = path.posix.resolve(input.privateSessionDir);
  const filePath = path.posix.resolve(
    historyDir,
    safeClineHistoryFileName(input.historyFileName),
  );
  const relativePath = path.posix.relative(historyDir, filePath);
  if (
    relativePath === '' ||
    relativePath.startsWith('..') ||
    path.posix.isAbsolute(relativePath)
  ) {
    throw new Error(
      `Invalid Cline history file name: ${input.historyFileName}`,
    );
  }
  return filePath;
}

/**
 * Persist the runtime's conversation history into private sandbox state so a
 * future process can resume the session after
 * `HarnessV1SandboxProvider.resume?.({ sessionId })` reattaches the sandbox.
 */
export async function persistHistoryToSandbox(args: {
  readonly sandbox: Experimental_SandboxSession;
  readonly privateSessionDir: string;
  readonly historyFileName: string;
  readonly messages: readonly AgentMessage[];
  readonly abortSignal?: AbortSignal;
}): Promise<void> {

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Pass only the bare file name (e.g. 'task-123.json'), not a path, and let the harness join it with the history directory.
  2. Sanitize the input: strip directory components and reject names containing '/', '..', or leading separators before calling the API.
  3. If the history file lives elsewhere, point the history directory configuration at its actual parent directory instead of using a relative name.

Example fix

// before
resolveClineResumeState({ historyFileName: `../../tasks/${taskId}.json` });
// after
if (!/^[A-Za-z0-9._-]+$/.test(taskId)) throw new Error('bad task id');
resolveClineResumeState({ historyFileName: `${taskId}.json` });
Defensive patterns

Strategy: validation

Validate before calling

function isValidHistoryFileName(name: string): boolean {
  return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name) && !name.startsWith('.') && !name.includes('/') && !path.posix.isAbsolute(name);
}
if (!isValidHistoryFileName(historyFileName)) throw new Error(`Refusing unsafe history file name: ${historyFileName}`);

Try / catch

try {
  await resolveClineResumeState({ historyFileName });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Invalid Cline history file name')) {
    historyFileName = path.posix.basename(historyFileName);
    // retry or surface a user-facing validation error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the resume-state API with historyFileName such as '../other-task.json', '/etc/passwd', an absolute path, an empty name, or a name that normalizes to the history directory itself (e.g. '.' or a nested path like 'a/../../x').

Common situations: Storing or deriving history file names from user input or task IDs without sanitizing; joining a history file name with the wrong base directory; migrating from an older Cline state layout where file names included subdirectories or absolute paths.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/429e6eaf18f54c14. Report an issue: GitHub.