{"record":{"id":"709e4c7496a95b0b","repo":"can1357/oh-my-pi","slug":"local-file-not-found-url-href","errorCode":null,"errorMessage":"Local file not found: ${url.href}","messagePattern":"Local file not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/local-protocol.ts","lineNumber":379,"sourceCode":"\n\tif (targetPath === resolvedRoot) {\n\t\treturn { kind: \"listing\", root: resolvedRoot };\n\t}\n\n\tconst parentDir = path.dirname(targetPath);\n\ttry {\n\t\tconst realParent = await fs.realpath(parentDir);\n\t\tensureWithinRoot(realParent, resolvedRoot);\n\t} catch (error) {\n\t\tif (!isEnoent(error)) throw error;\n\t}\n\n\tlet realTargetPath: string;\n\ttry {\n\t\trealTargetPath = await fs.realpath(targetPath);\n\t} catch (error) {\n\t\tif (isEnoent(error)) {\n\t\t\tthrow new Error(`Local file not found: ${url.href}`);\n\t\t}\n\t\tthrow error;\n\t}\n\n\tensureWithinRoot(realTargetPath, resolvedRoot);\n\n\tconst stat = await fs.stat(realTargetPath);\n\tif (stat.isDirectory()) {\n\t\treturn { kind: \"directory\", path: realTargetPath };\n\t}\n\tif (!stat.isFile()) {\n\t\tthrow new Error(`local:// URL must resolve to a file or directory: ${url.href}`);\n\t}\n\treturn { kind: \"file\", path: realTargetPath, size: stat.size };\n}\n\n/**\n * Resolve a local:// URL to a regular on-disk file, applying the same","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/local-protocol.ts#L361-L397","documentation":"After computing the target path and verifying containment, resolveLocalTarget calls fs.realpath on the target. When it fails with ENOENT the handler throws this friendly 'file not found' error carrying the original URL href, distinguishing a missing file from other fs failures.","triggerScenarios":"Reading local://notes.md when no notes.md was ever written under the session local root; a typo in the URL path; referencing a file from an earlier session whose local root was different; case-mismatched names on case-sensitive filesystems.","commonSituations":"Agents referencing local:// artifacts before writing them; sessions where copyLocalArtifacts did not run across a handoff so prior artifacts are absent; users assuming local:// spans the whole filesystem rather than the session root.","solutions":["Run a resolve of local:// (the root listing) to see which files actually exist.","Write the file first via the write tool with path local://<name>, then read it.","Fix typos / case in the URL path; remember local:// is scoped to the current session's local root, not the repo."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const listing = await handler.resolve(parseInternalUrl('local://'), ctx); // read listing content to confirm the file name exists","typeGuard":null,"tryCatchPattern":"try { resource = await handler.resolve(url, ctx); } catch (e) { if (String(e.message).startsWith('Local file not found')) { /* write the file first or correct the path */ } else throw e; }","preventionTips":["Resolve bare local:// first to list available files before referencing one.","Write via the write tool with path local://<name> before reading.","Remember local:// is session-scoped — files from prior sessions may not exist after handoff unless copyLocalArtifacts ran."],"tags":["filesystem","file-not-found","enoent"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}