different-ai/openwork · error · ApiError
invalid_path
invalid_path
Error message
Path must be absolute
What it means
assertAbsolute validates that a supplied filesystem path is absolute before the server resolves it; relative paths (or empty strings) raise this 400 ApiError with code invalid_path. The server API never interprets paths relative to its own CWD.
Source
Thrown at apps/server/src/paths.ts:7
import { realpath } from "node:fs/promises";
import { isAbsolute, resolve, sep } from "node:path";
import { ApiError } from "./errors.js";
export function assertAbsolute(path: string): void {
if (!isAbsolute(path)) {
throw new ApiError(400, "invalid_path", "Path must be absolute");
}
}
export async function resolveWithinRoot(root: string, ...segments: string[]): Promise<string> {
const resolvedRoot = await realpath(root);
const candidate = resolve(resolvedRoot, ...segments);
const resolvedCandidate = await realpath(candidate).catch(() => candidate);
if (resolvedCandidate === resolvedRoot) return candidate;
if (!resolvedCandidate.startsWith(resolvedRoot + sep)) {
throw new ApiError(400, "path_escape", "Path escapes workspace root");
}
return candidate;
}
View on GitHub (pinned to 2b7df46e8a)
Solutions
- Convert the path to absolute on the caller side (path.resolve / path.join with the workspace root) before sending.
- Prefix with the workspace root directory you registered with the server.
- Trim/handle empty strings before calling.
- In tests, build absolute paths from a tmpdir instead of fixtures.
Example fix
// before
await api.filePath({ path: "src/index.ts" });
// after
import { resolve } from "node:path";
await api.filePath({ path: resolve(workspaceRoot, "src/index.ts") }); Defensive patterns
Strategy: validation
Validate before calling
import { isAbsolute, resolve } from "node:path";
function toAbsolute(p: string, workspaceRoot: string): string {
const abs = resolve(workspaceRoot, p);
if (!isAbsolute(abs)) throw new Error(`Path must be absolute: ${p}`);
return abs;
} Type guard
function isAbsolutePath(p: string): boolean {
return typeof p === "string" && p.length > 0 && isAbsolute(p);
} Try / catch
import { ApiError } from "./errors.js";
try {
assertAbsolute(userPath);
} catch (err) {
if (err instanceof ApiError && err.code === "invalid_path") {
throw new ApiError(400, "invalid_path", `Provide an absolute path, got: ${userPath}`);
}
throw err;
} Prevention
- Always build paths with path.resolve(root, relative) before calling server APIs.
- Never rely on server-side CWD; the server has no concept of client CWD.
- Reject empty/whitespace paths in UI forms before submission.
- In tests, generate absolute paths from tmpdir fixtures.
When it happens
Trigger: Calling filePath or any path-taking API with a relative path like "src/foo.ts" or "./notes.txt", an empty path, or a path built from a URL-encoded relative segment.
Common situations: Clients assuming server-side CWD resolution; passing workspace-relative paths from UI code; forgetting path.resolve on the client; tests reusing relative fixtures.
Related errors
- invalid_payload
- invalid_cloud_plugin
- invalid_env_key
- MCP tool result was incomplete.
- ${failureLabel} (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/9701844604664e2c.
Report an issue: GitHub.