different-ai/openwork · error
Failed to load skill (${response.status}).
Error message
Failed to load skill (${response.status}). What it means
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.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/skill-data.tsx:92
function parseSkillResponse(payload: unknown): DenSkill | null {
return isRecord(payload) ? parseSkillPayload(payload.item) : null;
}
export function useSkill(pluginId: string, skillId: string) {
const { orgId } = useOrgDashboard();
const organizationId = orgId ?? "none";
return useQuery({
enabled: Boolean(orgId && pluginId && skillId),
queryKey: skillQueryKeys.detail(organizationId, pluginId, skillId),
queryFn: async (): Promise<DenSkill> => {
const encodedSkillId = encodeURIComponent(skillId);
const [{ response, payload }, membershipResult] = await Promise.all([
requestJson(`/v1/config-objects/${encodedSkillId}`, { method: "GET" }, 15000),
requestJson(`/v1/config-objects/${encodedSkillId}/plugins`, { method: "GET" }, 15000),
]);
if (!response.ok) {
throw new Error(getErrorMessage(payload, `Failed to load skill (${response.status}).`));
}
if (!membershipResult.response.ok) {
throw new Error(getErrorMessage(membershipResult.payload, `Failed to verify skill plugin (${membershipResult.response.status}).`));
}
const belongsToPlugin = isRecord(membershipResult.payload)
&& Array.isArray(membershipResult.payload.items)
&& membershipResult.payload.items.some((entry) => (
isRecord(entry) && entry.pluginId === pluginId && entry.removedAt === null
));
if (!belongsToPlugin) {
throw new Error("That skill is not part of this plugin.");
}
const skill = parseSkillResponse(payload);
if (!skill) {
throw new Error("Skill detail response was incomplete.");
}
return skill;
},View on GitHub (pinned to 2b7df46e8a)
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
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side preconditions before firing the request
if (!skillId || skillId.trim().length === 0) throw new Error("A skill id is required.");
if (!orgSlug) throw new Error("Load the skill within an organization context.");
// auth guard
const session = await getSession();
if (!session) throw new Error("Sign in to view this skill."); Type guard
function isConfigObjectPayload(payload: unknown): payload is { id: string; name: string; [k: string]: unknown } {
return typeof payload === "object" && payload !== null && "id" in payload && typeof (payload as { id: unknown }).id === "string";
} Try / catch
const { data, error, refetch } = useSkill(skillId, pluginId);
if (error) {
if (error.message.includes("404")) return <NotFound onBack={goBack} />;
if (error.message.includes("401") || error.message.includes("403")) return <SignInPrompt />;
return <ErrorState message={error.message} onRetry={refetch} />;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to load dashboards (${response.status}).
- Failed to load the dashboard (${response.status}).
- Failed to verify skill plugin (${membershipResult.response.s
- Failed to load Workflow (${response.status}).
- Failed to fetch latest-mac.yml (${response.status} ${respons
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/256ba3c3a5c2f289.
Report an issue: GitHub.