{"record":{"id":"7c0f8932297793f5","repo":"mastra-ai/mastra","slug":"skills-api-error-response-status-response-st-7c0f89","errorCode":null,"errorMessage":"Skills API error: ${response.status} ${response.statusText}","messagePattern":"Skills API error: (.+?) (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":502,"severity":"error","filePath":"packages/server/src/server/handlers/workspace.ts","lineNumber":1190,"sourceCode":"  path: '/workspaces/:workspaceId/skills-sh/search',\n  responseType: 'json',\n  pathParamSchema: workspaceIdPathParams,\n  queryParamSchema: skillsShSearchQuerySchema,\n  responseSchema: skillsShSearchResponseSchema,\n  summary: 'Search skills on skills.sh',\n  description: 'Proxies search requests to skills.sh API to avoid CORS issues',\n  tags: ['Workspace', 'Skills'],\n  handler: async ({ q, limit }) => {\n    try {\n      const controller = new AbortController();\n      const timeoutId = setTimeout(() => controller.abort(), 10000);\n\n      const url = `${SKILLS_SH_API_URL}/api/skills?query=${encodeURIComponent(q)}&pageSize=${limit}`;\n      const response = await fetch(url, { signal: controller.signal });\n      clearTimeout(timeoutId);\n\n      if (!response.ok) {\n        throw new HTTPException(502, {\n          message: `Skills API error: ${response.status} ${response.statusText}`,\n        });\n      }\n\n      const data = (await response.json()) as {\n        skills: Array<{\n          skillId: string;\n          name: string;\n          installs: number;\n          source: string;\n          owner: string;\n          repo: string;\n          githubUrl: string;\n          displayName: string;\n        }>;\n        total: number;\n        page: number;\n        pageSize: number;","sourceCodeStart":1172,"sourceCodeEnd":1208,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workspace.ts#L1172-L1208","documentation":"The skills.sh registry search proxies to SKILLS_SH_API_URL (/api/skills). If the upstream response is not ok, the handler wraps it into a 502 Bad Gateway including the upstream status and statusText. It signals an upstream registry problem, not an error in your request.","triggerScenarios":"Calling the skills registry search route while skills.sh returns a non-2xx (429 rate limit, 500, 503 outage), or network middleware returning an error page status.","commonSituations":"skills.sh rate limiting your IP; temporary registry outage; corporate proxy intercepting with 403; DNS handled but upstream degraded.","solutions":["Retry the request after a short backoff (the upstream may be transiently failing).","Check the upstream status in the message (e.g. 429 → wait, 5xx → outage) and inspect https://skills.sh availability.","If rate limited (429), reduce request frequency or add caching of search results.","Verify no proxy/firewall is altering the response between the server and skills.sh."],"exampleFix":"// before\nconst res = await fetch('/workspaces/ws1/skills/registry/search?query=pdf');\n// after\ntry {\n  const res = await fetch('/workspaces/ws1/skills/registry/search?query=pdf');\n} catch (e) {\n  await new Promise(r => setTimeout(r, 1000)); // backoff then retry\n}","handlingStrategy":"retry","validationCode":"const controller = new AbortController();\nconst timeout = setTimeout(() => controller.abort(), 10_000); // fail fast before the 502 surfaces downstream","typeGuard":"function isUpstreamError(e: unknown): e is { status: number; message: string } {\n  return typeof e === 'object' && e !== null && 'status' in e && (e as any).status === 502;\n}","tryCatchPattern":"try {\n  return await client.searchSkillRegistry({ query, limit });\n} catch (e) {\n  if (isUpstreamError(e)) {\n    await sleep(retryAfterFrom(e) ?? 1000);\n    return await client.searchSkillRegistry({ query, limit }); // retry once with backoff\n  }\n  throw e;\n}","preventionTips":["Wrap registry calls in retry-with-backoff (upstream 5xx is usually transient).","Cache search results to reduce upstream pressure.","Watch for 429 in the message and back off accordingly.","Have a fallback (local skills search) for registry outages."],"tags":["http-502","network","upstream","registry","skills"],"backgroundTag":"upstream-service-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}