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

  1. Read the server message in the error to distinguish permission (403), missing (404), and conflict (409).
  2. On 404, treat deletion as already-done: invalidate queries and remove from UI instead of surfacing an error.
  3. If it is a ReauthRequiredError that escaped, prompt sign-in and retry the delete.
  4. Check org role/policy — deleting may require an admin or Den-side allowlist.
  5. 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

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


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/8b00b966f124132e. Report an issue: GitHub.