{"record":{"id":"256ba3c3a5c2f289","repo":"different-ai/openwork","slug":"failed-to-load-skill-response-status","errorCode":null,"errorMessage":"Failed to load skill (${response.status}).","messagePattern":"Failed to load skill \\((.+?)\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/skill-data.tsx","lineNumber":92,"sourceCode":"function parseSkillResponse(payload: unknown): DenSkill | null {\n  return isRecord(payload) ? parseSkillPayload(payload.item) : null;\n}\n\nexport function useSkill(pluginId: string, skillId: string) {\n  const { orgId } = useOrgDashboard();\n  const organizationId = orgId ?? \"none\";\n\n  return useQuery({\n    enabled: Boolean(orgId && pluginId && skillId),\n    queryKey: skillQueryKeys.detail(organizationId, pluginId, skillId),\n    queryFn: async (): Promise<DenSkill> => {\n      const encodedSkillId = encodeURIComponent(skillId);\n      const [{ response, payload }, membershipResult] = await Promise.all([\n        requestJson(`/v1/config-objects/${encodedSkillId}`, { method: \"GET\" }, 15000),\n        requestJson(`/v1/config-objects/${encodedSkillId}/plugins`, { method: \"GET\" }, 15000),\n      ]);\n      if (!response.ok) {\n        throw new Error(getErrorMessage(payload, `Failed to load skill (${response.status}).`));\n      }\n      if (!membershipResult.response.ok) {\n        throw new Error(getErrorMessage(membershipResult.payload, `Failed to verify skill plugin (${membershipResult.response.status}).`));\n      }\n      const belongsToPlugin = isRecord(membershipResult.payload)\n        && Array.isArray(membershipResult.payload.items)\n        && membershipResult.payload.items.some((entry) => (\n          isRecord(entry) && entry.pluginId === pluginId && entry.removedAt === null\n        ));\n      if (!belongsToPlugin) {\n        throw new Error(\"That skill is not part of this plugin.\");\n      }\n      const skill = parseSkillResponse(payload);\n      if (!skill) {\n        throw new Error(\"Skill detail response was incomplete.\");\n      }\n      return skill;\n    },","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/skill-data.tsx#L74-L110","documentation":"Thrown inside useSkill's TanStack Query fetcher when the GET /v1/config-objects/{id} request returns a non-ok status. getErrorMessage(payload, fallback) is used so the server-provided error message surfaces when present, with the status-code string as the fallback. This is the primary skill-detail fetch failing, which leaves the skill page in an error state.","triggerScenarios":"GET /v1/config-objects/{encodedSkillId} responds 401/403 (no session or no permission for this org's config object), 404 (skill id wrong, skill deleted, or wrong org), or 5xx from the API.","commonSituations":"Bookmarked/shared URL pointing to a deleted or renamed skill; cross-org access attempt; expired auth token; URL-encoding mismatch producing a wrong id on the server; API outage returning 502/503.","solutions":["Check the response status and payload in the network tab to identify 401 vs 404 vs 5xx","Verify the skillId in the URL exists in the target org (config-objects list)","Re-authenticate if 401; confirm the user's role grants read access to config objects if 403","Retry on 5xx / check den-api server health and logs"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// client-side preconditions before firing the request\nif (!skillId || skillId.trim().length === 0) throw new Error(\"A skill id is required.\");\nif (!orgSlug) throw new Error(\"Load the skill within an organization context.\");\n// auth guard\nconst session = await getSession();\nif (!session) throw new Error(\"Sign in to view this skill.\");","typeGuard":"function isConfigObjectPayload(payload: unknown): payload is { id: string; name: string; [k: string]: unknown } {\n  return typeof payload === \"object\" && payload !== null && \"id\" in payload && typeof (payload as { id: unknown }).id === \"string\";\n}","tryCatchPattern":"const { data, error, refetch } = useSkill(skillId, pluginId);\nif (error) {\n  if (error.message.includes(\"404\")) return <NotFound onBack={goBack} />;\n  if (error.message.includes(\"401\") || error.message.includes(\"403\")) return <SignInPrompt />;\n  return <ErrorState message={error.message} onRetry={refetch} />;\n}","preventionTips":["Handle 404 skill ids with a friendly not-found page instead of a raw error","Refresh auth tokens before long-lived dashboard sessions","Use TanStack Query retry with backoff for 5xx (but not 4xx)","Verify shared skill links include the correct org slug"],"tags":["network","http","react-query","skill"],"backgroundTag":"http-request-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}