different-ai/openwork · error
Failed to delete skill (${response.status}).
Error message
Failed to delete skill (${response.status}). What it means
Thrown by useDeleteSkill when POST /v1/config-objects/{skillId}/delete returns a non-ok status. Deletion is modeled as a POST to a /delete action endpoint and is wrapped in runReauthableAction so 403 reauth challenges are retried after re-authentication; any other failure surfaces this error with the server's message. The skill cache is only cleared on success.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/skill-data.tsx:192
]);
},
});
}
export function useDeleteSkill(pluginId: string) {
const queryClient = useQueryClient();
const { runReauthableAction } = useOrgDashboard();
return useMutation({
mutationFn: async (skillId: string): Promise<string> => {
await runReauthableAction("delete-skill", async () => {
const { response, payload } = await requestJson(
`/v1/config-objects/${encodeURIComponent(skillId)}/delete`,
{ method: "POST" },
15000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Failed to delete skill (${response.status}).`);
}
});
return skillId;
},
onSuccess: async () => {
await queryClient.cancelQueries({ queryKey: skillQueryKeys.all });
queryClient.removeQueries({ queryKey: skillQueryKeys.all });
await queryClient.invalidateQueries({ queryKey: pluginQueryKeys.detail(pluginId) });
},
});
}
View on GitHub (pinned to 2b7df46e8a)
Solutions
- Read the server message in the error to distinguish permission (403), missing (404), and conflict (409).
- On 404, treat deletion as already-done: invalidate queries and remove from UI instead of surfacing an error.
- If it is a ReauthRequiredError that escaped, prompt sign-in and retry the delete.
- Check org role/policy — deleting may require an admin or Den-side allowlist.
- Retry on 429/5xx with backoff; check Den server health for persistent 5xx.
Example fix
// before
deleteSkill.mutate(skillId, { onError: (e) => alert(e.message) });
// after: tolerate already-deleted (404)
deleteSkill.mutate(skillId, {
onError: (e) => {
if (/\b404\b/.test(e.message)) {
queryClient.invalidateQueries({ queryKey: skillQueryKeys.all });
return;
}
alert(e.message);
},
}); Defensive patterns
Strategy: try-catch
Validate before calling
if (!skillId) throw new Error("skillId is required to delete a skill.");
// optionally confirm existence first:
const res = await fetch(`/v1/config-objects/${encodeURIComponent(skillId)}`);
if (res.status === 404) { /* already gone; skip delete */ } Type guard
function isReauthRequiredError(e: unknown): e is ReauthRequiredError {
return e instanceof ReauthRequiredError;
} Try / catch
try {
await deleteSkill.mutateAsync(skillId);
} catch (err) {
if (isReauthRequiredError(err)) { promptSignIn(); return; }
if (/\b404\b/.test(err.message)) { cleanupLocalState(); return; } // already deleted
showError(err.message);
} Prevention
- Delete is already wrapped in runReauthableAction — keep it that way when refactoring.
- Treat 404 as success (idempotent delete) in UI error handling.
- Confirm org role allows deletion before showing the delete button.
- Invalidate skill and plugin queries only after success, as the hook does.
- For 429/5xx, surface a retryable error rather than a hard failure.
When it happens
Trigger: POST /v1/config-objects/{skillId}/delete returns 401 (expired token after runReauthableAction exhausted its re-auth path), 403 (no delete permission / org policy), 404 (skill already deleted elsewhere), 409 (skill is referenced/locked, e.g. attached to a published plugin version), 429, or 5xx. 15s timeout.
Common situations: Two admins delete the same skill concurrently (second gets 404); org policy forbids deleting skills in use by an active plugin; session fully expired so even reauth cannot proceed; Den server outage returns 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 create skill (${response.status}).
- Failed to save skill (${response.status}).
- Failed to load organizations (${response.status}).
- Failed to switch organization (${response.status}).
- Failed to load organization (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/8b00b966f124132e.
Report an issue: GitHub.