{"record":{"id":"0c1770fd20c13345","repo":"mastra-ai/mastra","slug":"reference-decodedpath-not-found-in-skill-i","errorCode":null,"errorMessage":"Reference \"${decodedPath}\" not found in skill \"${identifier}\"","messagePattern":"Reference \"(.+?)\" not found in skill \"(.+?)\"","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"packages/server/src/server/handlers/workspace.ts","lineNumber":1091,"sourceCode":"        throw new HTTPException(404, { message: `Skill \"${identifier}\" not found` });\n      }\n\n      // Decode the reference path (it may be URL encoded)\n      let decodedPath: string;\n      try {\n        decodedPath = decodeURIComponent(referencePath);\n      } catch {\n        throw new HTTPException(400, { message: 'Malformed referencePath' });\n      }\n\n      // Prevent path traversal via the reference path parameter\n      assertSafeFilePath(decodedPath);\n\n      // getReference expects a path relative to skill.path, so prepend 'references/'\n      // since the URL path already contains the literal /references/ segment\n      const content = await skills.getReference(identifier, `references/${decodedPath}`);\n      if (content === null) {\n        throw new HTTPException(404, {\n          message: `Reference \"${decodedPath}\" not found in skill \"${identifier}\"`,\n        });\n      }\n\n      return {\n        skillName: skill.name,\n        referencePath: decodedPath,\n        content,\n      };\n    } catch (error) {\n      return handleWorkspaceError(error, 'Error getting skill reference');\n    }\n  },\n});\n\nexport const WORKSPACE_SEARCH_SKILLS_ROUTE = createRoute({\n  method: 'GET',\n  path: '/workspaces/:workspaceId/skills/search',","sourceCodeStart":1073,"sourceCodeEnd":1109,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workspace.ts#L1073-L1109","documentation":"After validating the decoded path, the handler calls `skills.getReference(identifier, 'references/<decodedPath>')`. When the skill exists but the referenced file does not, getReference returns null and the handler throws a 404 naming the reference path and skill.","triggerScenarios":"GET .../skills/:identifier/references/:referencePath where the decoded path does not correspond to a file under the skill's references/ directory, or it was rejected earlier by assertSafeFilePath (path traversal) — though traversal has its own error, a null return here means simply 'no such reference file'.","commonSituations":"Typo in the reference filename; wrong file extension (.txt vs .md); reference file deleted or not shipped with the skill; requesting a path outside references/ assuming root-relative paths.","solutions":["List the skill's references (skills.listReferences / the references listing endpoint) and use an exact file path.","Remember the path is relative to the skill's references/ directory — do not prepend 'references/' yourself.","Check the file exists in the skill package on disk and was deployed.","Fix the file extension/case to match the actual file."],"exampleFix":"// before\nGET /skills/my-skill/references/Reference.md\n// after\nGET /skills/my-skill/references/reference.md","handlingStrategy":"try-catch","validationCode":"const refs = await client.listSkillReferences(workspaceId, identifier);\nif (!refs.includes(decodedPath)) {\n  throw new Error(`Reference \"${decodedPath}\" unavailable; have: ${refs.join(', ')}`);\n}","typeGuard":"function referenceExists(refs: string[], path: string): boolean {\n  return refs.includes(path.replace(/^\\/+/, ''));\n}","tryCatchPattern":"try {\n  return await client.getSkillReference({ skillName, referencePath });\n} catch (e) {\n  if (isHttpException(e, 404)) {\n    const refs = await client.listSkillReferences(workspaceId, skillName);\n    console.warn(`Missing reference. Available: ${refs}`);\n    return null;\n  }\n  throw e;\n}","preventionTips":["List references before fetching; treat the list as the source of truth.","Do not prepend 'references/' yourself — the route does it.","Match file names and extensions exactly, including case."],"tags":["http-404","skills","file-not-found","rest-api"],"backgroundTag":"resource-not-found-404","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}