different-ai/openwork · error · ApiError
file_not_found
file_not_found
Error message
File was not found inside an authorized workspace root.
What it means
If none of the authorized roots resolves to a real file containing the requested path, resolveAuthorizedFile throws a 404 file_not_found ApiError, preventing path-traversal uploads outside the workspace.
Source
Thrown at apps/server/src/extensions/cloud-uploads.ts:145
if (!roots.some((root) => isWithinRoot(candidate, root))) continue;
try {
const realCandidate = await realpath(candidate);
if (!realRoots.some((root) => isWithinRoot(realCandidate, root))) continue;
const info = await stat(realCandidate);
if (!info.isFile()) continue;
if (info.size < 1 || info.size > DIRECT_UPLOAD_MAX_BYTES) {
throw new ApiError(413, "file_too_large", `Direct uploads support files up to ${DIRECT_UPLOAD_MAX_BYTES} bytes.`, {
size: info.size,
maxBytes: DIRECT_UPLOAD_MAX_BYTES,
});
}
return realCandidate;
} catch (error) {
if (isRecord(error) && error.code === "ENOENT") continue;
throw error;
}
}
throw new ApiError(404, "file_not_found", "File was not found inside an authorized workspace root.", { path: requested });
}
function mimeTypeForPath(path: string) {
const lower = path.toLowerCase();
if (lower.endsWith(".pdf")) return "application/pdf";
if (lower.endsWith(".docx")) return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
if (lower.endsWith(".xlsx")) return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
if (lower.endsWith(".pptx")) return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
if (lower.endsWith(".csv")) return "text/csv";
if (lower.endsWith(".txt")) return "text/plain";
if (lower.endsWith(".json")) return "application/json";
if (lower.endsWith(".png")) return "image/png";
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
return "application/octet-stream";
}
async function cloudUploadEndpoint(config: ServerConfig, suffix: string, dependencies: CloudUploadDependencies) {
const cloud = await (dependencies.readCloudMcp ?? readConnectCloudMcp)(config);View on GitHub (pinned to 2b7df46e8a)
Solutions
- Verify the path exists on disk and is spelled correctly, and that it's inside a configured workspace root
- Pass an absolute path within an authorized root rather than a relative one
- Replace symlinks with the real file inside the root (symlinks escaping the root are rejected by the realpath check)
- Recreate the file if it was moved or deleted since selection
Example fix
// before
await upload("../secrets/creds.txt"); // outside workspace
// after
await upload("/Users/me/projects/app/notes/notes.pdf"); // inside root Defensive patterns
Strategy: validation
Validate before calling
const real = await realpath(p); const inside = (await Promise.all(roots.map(r => realpath(r)))).some(r => real.startsWith(r + sep)); if (!inside) throw new Error("outside workspace"); Try / catch
try { await uploadCloud(p); } catch (e) { if (e.code === "file_not_found") { promptRepickFile(); } else throw e; } Prevention
- Use workspace-scoped file pickers only
- Resolve symlinks before upload
- Confirm existence immediately before upload
When it happens
Trigger: Requesting an upload of a path that doesn't exist, or exists but lies outside every authorized root (including symlinked paths whose realpath escapes the roots).
Common situations: Typo in the path; file deleted before upload; absolute path outside the workspace; relative path resolving against the wrong cwd; symlink pointing outside the root (realpath check rejects it).
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/1d4a579459e13047.
Report an issue: GitHub.