{"record":{"id":"b3b8e5de290c64de","repo":"mastra-ai/mastra","slug":"skills-api-error-response-status-response-st","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/skills-sh-shared.ts","lineNumber":153,"sourceCode":"    displayName: string;\n  }>;\n  total: number;\n  page?: number;\n  pageSize?: number;\n  totalPages?: number;\n}\n\n/** Search skills.sh by query string. Throws HTTPException on upstream failure. */\nexport async function searchSkillsSh({ q, limit }: { q: string; limit: number }): Promise<SkillsShSearchResult> {\n  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), SEARCH_TIMEOUT_MS);\n\n  try {\n    const url = `${SKILLS_SH_API_URL}/api/skills?query=${encodeURIComponent(q)}&pageSize=${limit}`;\n    const response = await fetch(url, { signal: controller.signal });\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 UpstreamSkillsList;\n    return {\n      query: q,\n      searchType: 'query',\n      skills: data.skills.map(s => ({ id: s.skillId, name: s.name, installs: s.installs, topSource: s.source })),\n      count: data.total,\n    };\n  } finally {\n    clearTimeout(timeoutId);\n  }\n}\n\n/** Fetch the popular skills list from skills.sh. */\nexport async function getPopularSkillsSh({","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/skills-sh-shared.ts#L135-L171","documentation":"A 502 Bad Gateway raised by `searchSkillsSh` when the skills.sh registry API responds with a non-OK HTTP status. The server proxies search requests to SKILLS_SH_API_URL and surfaces upstream failures as 502 so clients know the problem is with the upstream registry, not their query.","triggerScenarios":"Calling the builder registry search route while skills.sh is down, rate-limiting (429), returning 5xx, or an intermittent proxy/firewall altering the response.","commonSituations":"skills.sh outage or maintenance; network egress blocked from a self-hosted server; upstream rate limits under heavy search traffic; DNS/CDN errors producing non-OK statuses.","solutions":["Retry the search after a short delay; upstream hiccups are often transient.","Check skills.sh status directly (curl the API URL) to confirm an outage.","Verify outbound network/egress from the Mastra server host (proxy, firewall, DNS).","Inspect the status/statusText in the message (429 vs 500) to decide between backoff and outage handling."],"exampleFix":"// before\nconst results = await searchSkills('react'); // throws 502 on upstream failure\n// after\nasync function searchSkillsSafe(q) {\n  try { return await searchSkills(q); }\n  catch (e) {\n    if (e?.status === 502) { await new Promise(r => setTimeout(r, 1000)); return searchSkills(q); }\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const results = await searchSkills(q);\n  return results;\n} catch (e) {\n  if (e instanceof MastraClientError && e.status === 502) {\n    // upstream skills.sh failure — retry with backoff or serve cached results\n    await new Promise(r => setTimeout(r, 1000));\n    return searchSkills(q);\n  }\n  throw e;\n}","preventionTips":["Cache search results to tolerate transient registry outages.","Monitor skills.sh availability from your server host.","Confirm firewall/proxy rules allow outbound HTTPS to skills.sh."],"tags":["network","http-502","upstream-api","skills-registry"],"backgroundTag":"upstream-api-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}