{"record":{"id":"49059b4df31a7844","repo":"can1357/oh-my-pi","slug":"path-localreadpath-not-found","errorCode":null,"errorMessage":"Path '${localReadPath}' not found","messagePattern":"Path '(.+?)' not found","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/read.ts","lineNumber":1305,"sourceCode":"\t\t\t\t\tconst approvedPlanPath = this.#approvedPlanAlias(absolutePath);\n\t\t\t\t\tif (approvedPlanPath) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst approvedPlanStat = await Bun.file(approvedPlanPath).stat();\n\t\t\t\t\t\t\tabsolutePath = approvedPlanPath;\n\t\t\t\t\t\t\tfileSize = approvedPlanStat.size;\n\t\t\t\t\t\t\tisDirectory = approvedPlanStat.isDirectory();\n\t\t\t\t\t\t\trecoveredApprovedPlan = true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// The referenced plan disappeared after resolution; continue through\n\t\t\t\t\t\t\t// the ordinary delimited-path fallback and not-found error.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!recoveredApprovedPlan && !suffixResolution) {\n\t\t\t\t\tconst delimitedResult = await this.#tryReadDelimitedPaths(readPath, signal);\n\t\t\t\t\tif (delimitedResult) return delimitedResult;\n\t\t\t\t\tthrow new ToolError(`Path '${localReadPath}' not found`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tif (isDirectory) {\n\t\t\tif (isMultiRange(parsed)) {\n\t\t\t\tthrow new ToolError(\"Multi-range line selectors are not supported for directory listings.\");\n\t\t\t}\n\t\t\tconst { offset, limit } = selToOffsetLimit(parsed);\n\t\t\t// Directory listings are deterministic and fast; never abort them mid-scan\n\t\t\t// (an interrupt would otherwise surface a misleading \"Operation aborted\").\n\t\t\tconst dirResult = await this.#readDirectory(absolutePath, offset, limit, undefined);\n\t\t\tif (suffixResolution) {\n\t\t\t\tdirResult.details ??= {};\n\t\t\t\tdirResult.details.suffixResolution = suffixResolution;\n\t\t\t}","sourceCodeStart":1287,"sourceCodeEnd":1323,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/read.ts#L1287-L1323","documentation":"After the read path fails initial filesystem resolution, ReadTool tries recovery paths (approved plan recovery, suffix/glob resolution, delimited multi-path reads). If none succeed, it throws a plain 'Path not found' ToolError naming the local path it attempted.","triggerScenarios":"read() on a path that does not exist, with no glob-suffix match and no delimited-path alternative: e.g. read('/repo/src/missing.ts'), a typo'd path, or a file outside the workspace root when no suffix can recover it.","commonSituations":"Stale references after a rename/delete, case-sensitivity mismatches on Linux, typos in agent-generated paths, or reading a file that was never created.","solutions":["Verify the path exists (ls the parent directory) and fix the spelling/casing.","Use the exact path from a previous successful read or directory listing.","If the file was deleted/renamed, re-locate it via grep or directory read before retrying."],"exampleFix":"// before\nread(\"src/ap.ts\")\n// after\nread(\"src/app.ts\")  // path verified via directory listing","handlingStrategy":"try-catch","validationCode":"if (!fs.existsSync(localReadPath)) { /* locate via glob or directory listing before read */ }","typeGuard":"null","tryCatchPattern":"try { return await read(path) } catch (e) { if (e instanceof ToolError && e.message.includes('not found')) { const alt = await glob('**/'+path.basename(path)); if (alt[0]) return await read(alt[0]); } throw e; }","preventionTips":["Derive paths from directory listings or prior read results, never from memory","Watch for case-sensitivity on Linux filesystems","Re-verify paths after any rename/delete operation"],"tags":["filesystem","path-not-found","read-tool"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}