{"record":{"id":"2cdc374112a4dab8","repo":"can1357/oh-my-pi","slug":"path-not-found-scopepath","errorCode":null,"errorMessage":"Path not found: ${scopePath}","messagePattern":"Path not found: (.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/glob.ts","lineNumber":386,"sourceCode":"\t\t\t\t\t.text(truncation.content)\n\t\t\t\t\t.limits({ resultLimit: limitMeta.resultLimit?.reached });\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tresultBuilder.truncation(truncation, { direction: \"head\" });\n\t\t\t\t}\n\n\t\t\t\treturn resultBuilder.done();\n\t\t\t};\n\n\t\t\t// Walk each user path as its own root and run the globs concurrently.\n\t\t\t// Collapsing multiple paths to a shared base would force the walker to\n\t\t\t// traverse and stat every unrelated sibling under that ancestor; per-path\n\t\t\t// roots keep each scan bounded to exactly what the user asked for.\n\t\t\tif (this.#customOps?.glob) {\n\t\t\t\tconst customOps = this.#customOps;\n\t\t\t\tconst perTarget = await Promise.all(\n\t\t\t\t\ttargets.map(async target => {\n\t\t\t\t\t\tif (!(await customOps.exists(target.searchPath))) {\n\t\t\t\t\t\t\tif (isSingle) throw new ToolError(`Path not found: ${scopePath}`);\n\t\t\t\t\t\t\treturn [] as string[];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!target.hasGlob && customOps.stat) {\n\t\t\t\t\t\t\tconst stat = await customOps.stat(target.searchPath);\n\t\t\t\t\t\t\tif (stat.isFile()) return [formatScopePath(target.searchPath)];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst results = await customOps.glob(target.globPattern, target.searchPath, {\n\t\t\t\t\t\t\tignore: [\"**/node_modules/**\", \"**/.git/**\"],\n\t\t\t\t\t\t\tlimit: effectiveLimit,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn results.map(matchPath => formatMatchPath(matchPath, target.searchPath));\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst seen = new Set<string>();\n\t\t\t\tconst merged: string[] = [];\n\t\t\t\tfor (const group of perTarget) {\n\t\t\t\t\tfor (const entry of group) {\n\t\t\t\t\t\tif (seen.has(entry)) continue;","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/glob.ts#L368-L404","documentation":"When custom operations (customOps.glob) are configured, execute() checks each search target's existence via customOps.exists before scanning. If the path does not exist and a single path was requested, a clean 'Path not found' ToolError is thrown instead of an empty result or raw fs error.","triggerScenarios":"Calling the glob tool with a single non-existent path while customOps is active (e.g. virtual/sandboxed filesystem ops); typos in the directory path; deleted or moved directories.","commonSituations":"Path computed from stale session state; relative paths resolved against the wrong cwd; referencing a file that was deleted by a prior tool call.","solutions":["Verify the path exists before calling (fs stat / customOps.exists)","Fix the path spelling and ensure it is resolved against the intended cwd","For multiple targets, note non-existent ones are skipped (empty results) rather than throwing — only single-target calls throw"],"exampleFix":"// before\nawait globTool.execute({ pattern: \"*.ts\", path: \"src/typos\" })\n// after\nif (await fs.stat(\"src/tools\").catch(() => null)) {\n  await globTool.execute({ pattern: \"*.ts\", path: \"src/tools\" })\n}","handlingStrategy":"validation","validationCode":"const st = await fs.stat(p).catch(() => null);\nif (!st) throw new Error(`Target path does not exist: ${p}`);\nawait globTool.execute({ pattern, path: p });","typeGuard":"async function pathExists(p: string): Promise<boolean> {\n  return (await fs.stat(p).catch(() => null)) !== null;\n}","tryCatchPattern":"try {\n  return await globTool.execute({ pattern, path });\n} catch (err) {\n  if (err instanceof ToolError && err.message.startsWith(\"Path not found:\")) {\n    return []; // treat as no matches for the missing target\n  }\n  throw err;\n}","preventionTips":["Stat the target before globbing","Re-verify paths held in long-lived state still exist","Use multi-target calls if you want missing paths skipped rather than fatal"],"tags":["filesystem","path-not-found","glob-tool"],"backgroundTag":"path-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}