{"record":{"id":"a6f772bb8a4badef","repo":"can1357/oh-my-pi","slug":"skill-path-does-not-exist-url","errorCode":null,"errorMessage":"skill:// path does not exist: ${url}","messagePattern":"skill:// path does not exist: (.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/bash-skill-urls.ts","lineNumber":117,"sourceCode":"\t}\n\n\tconst targetPath = path.join(skill.baseDir, relativePath);\n\tconst resolvedPath = path.resolve(targetPath);\n\tconst resolvedBaseDir = path.resolve(skill.baseDir);\n\tif (!resolvedPath.startsWith(resolvedBaseDir + path.sep) && resolvedPath !== resolvedBaseDir) {\n\t\tthrow new ToolError(\"Path traversal is not allowed in skill:// URLs\");\n\t}\n\t// Agent Plugin skills (§4.1): the resource must canonically resolve within\n\t// the plugin root. Fail closed: a dangling or unresolvable path is rejected\n\t// rather than handed to bash, where writing through it could create the\n\t// outside target. Symlinks may target other files inside the same package.\n\tif (skill.containRoot) {\n\t\tconst contained = resolveContainedPathSync(skill.containRoot, resolvedPath);\n\t\tif (contained.status === \"outside\") {\n\t\t\tthrow new ToolError(`skill:// path resolves outside the plugin root: ${url}`);\n\t\t}\n\t\tif (contained.status === \"missing\") {\n\t\t\tthrow new ToolError(`skill:// path does not exist: ${url}`);\n\t\t}\n\t\treturn contained.realPath;\n\t}\n\n\treturn resolvedPath;\n}\n\n/**\n * Match a raw skill segment against registered skills using longest-prefix match.\n * Handles colons in both skill names (namespacing) and suffixes (line ranges).\n *\n * For \"superpowers:brainstorming:1-5\" with skill \"superpowers:brainstorming\":\n *   -> skill = superpowers:brainstorming, suffix = \"1-5\"\n * For \"brainstorming\" with skill \"brainstorming\":\n *   -> skill = brainstorming, suffix = undefined\n */\nfunction matchSkillName(\n\trawSegment: string,","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/bash-skill-urls.ts#L99-L135","documentation":"For containRoot skills, resolveContainedPathSync must be able to resolve the target's real path; a \"missing\" status (dangling symlink or nonexistent file) throws this ToolError rather than handing a broken path to bash. This is the fail-closed counterpart of the containment check: unresolvable paths are rejected.","triggerScenarios":"A skill:// URL like \"skill://name/docs/missing.md\" for a containRoot skill where the file does not exist, or where the final path component is a symlink whose target was deleted (dangling link).","commonSituations":"The model guesses a filename inside the skill that isn't there; the skill's docs changed between versions; a symlink target was removed after packaging; case-sensitivity mismatch (README.md vs readme.md) on case-sensitive filesystems.","solutions":["List the skill directory to find the correct file name, then retry with the exact name.","Check case sensitivity — file names must match exactly.","If a symlink is dangling, restore its target or remove the link from the package.","Reinstall/update the plugin if its files are missing from the installed copy."],"exampleFix":"// before\nresolveSkillUrlToPath(\"skill://my-skill/reference.md\", skills);\n// skill:// path does not exist\n\n// after\nresolveSkillUrlToPath(\"skill://my-skill/references/index.md\", skills);","handlingStrategy":"fallback","validationCode":"import * as fs from \"node:fs\";\nconst target = /* baseDir + decoded relative path */;\ntry { fs.realpathSync(target); } catch { throw new Error(`skill file missing: ${target}`); }","typeGuard":null,"tryCatchPattern":"try {\n  return resolveSkillUrlToPath(url, skills);\n} catch (e) {\n  if (e instanceof ToolError && e.message.includes(\"does not exist\")) {\n    // fall back: list the skill directory and retry with an existing file\n  } else throw e;\n}","preventionTips":["Enumerate actual skill files before referencing them instead of guessing names.","Match file names exactly, watching case sensitivity.","After plugin updates, refresh any cached file references.","Check for dangling symlinks when packaging skills."],"tags":["filesystem","file-not-found","skills"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}