{"record":{"id":"b52087029cb039b2","repo":"n8n-io/n8n","slug":"file-not-found-path","errorCode":null,"errorMessage":"File not found: ${path}","messagePattern":"File not found: (.+?)","errorType":"exception","errorClass":"DaytonaFileNotFoundError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/workspace/filesystem/daytona-filesystem.ts","lineNumber":161,"sourceCode":"\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\t// A genuine 404 means the file is absent. Sandbox/provider errors (e.g. a\n\t\t\t\t// stopped sandbox) must bubble up so withFilesystem() can recover instead of\n\t\t\t\t// silently reporting the file as missing.\n\t\t\t\tif (isDaytona404(error)) return false;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}, options?.abortSignal);\n\t}\n\n\tasync stat(path: string, options?: AbortableOptions): Promise<FileStat> {\n\t\treturn await this.withFs(async (fs) => {\n\t\t\tlet info;\n\t\t\ttry {\n\t\t\t\tinfo = await fs.getFileDetails(path);\n\t\t\t} catch (error: unknown) {\n\t\t\t\tif (isDaytona404(error)) {\n\t\t\t\t\tthrow new DaytonaFileNotFoundError(path);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tname: info.name ?? path.split('/').pop() ?? '',\n\t\t\t\tpath,\n\t\t\t\ttype: info.isDir ? 'directory' : 'file',\n\t\t\t\tsize: info.size ?? 0,\n\t\t\t\tcreatedAt: new Date(info.modTime ?? 0),\n\t\t\t\tmodifiedAt: new Date(info.modTime ?? 0),\n\t\t\t};\n\t\t}, options?.abortSignal);\n\t}\n}\n\nclass DaytonaFileNotFoundError extends Error {\n\tconstructor(path: string) {\n\t\tsuper(`File not found: ${path}`);","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/workspace/filesystem/daytona-filesystem.ts#L143-L179","documentation":"DaytonaFilesystem.stat() delegates to the Daytona SDK's getFileDetails(). When the SDK rejects with a 404 (detected by isDaytona404: an Error with `statusCode === 404`), the adapter rethrows it as a typed DaytonaFileNotFoundError whose message is `File not found: <path>`. This lets callers distinguish a genuinely missing file from transport/auth/provider errors.","triggerScenarios":"Calling stat() (or any built-in tool routed through it) on a path that does not exist in the Daytona sandbox: a typo, a wrong relative path resolved against an unexpected cwd, a case mismatch on a case-sensitive FS, or a file deleted between a list and a stat.","commonSituations":"An agent tool call references a path it assumed existed; the working directory differed from what the agent expected; another process removed the file mid-workflow; cross-platform path separators (`\\` vs `/`).","solutions":["Verify the absolute path and casing against the sandbox working directory before calling stat.","If existence is uncertain, list the parent first or treat the not-found error as a soft 'no'.","Catch by error.name === 'DaytonaFileNotFoundError' and surface a clean not-found to the user instead of a raw stack."],"exampleFix":"// before\nconst info = await fs.stat(maybePath);\n\n// after\ntry {\n  return await fs.stat(maybePath);\n} catch (e) {\n  if (e instanceof Error && e.name === 'DaytonaFileNotFoundError') return null;\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isDaytonaFileNotFound(e: unknown): boolean {\n  return e instanceof Error && e.name === 'DaytonaFileNotFoundError';\n}","tryCatchPattern":"try {\n  return await fs.stat(path);\n} catch (e) {\n  if (isDaytonaFileNotFound(e)) return null; // treat as 'not found'\n  throw e;\n}","preventionTips":["Use absolute paths and verify casing on case-sensitive sandboxes.","When existence is uncertain, list the parent directory first.","Catch by error.name === 'DaytonaFileNotFoundError' rather than string-matching the message."],"tags":["filesystem","daytona","not-found","agents"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}