Significant-Gravitas/AutoGPT · warning · HTTPException
'{slug}' is a built-in skill and cannot be deleted
Error message
'{slug}' is a built-in skill and cannot be deleted What it means
Skill-delete endpoint returns 400 when `delete_user_skill` raises BuiltInSkillError — the target slug resolves to a packaged default skill, which is shared across all users and therefore not user-deletable. The exception message is passed through verbatim ('{slug}' is a built-in skill and cannot be deleted). The detail endpoint flags these with is_default=True precisely so UIs can hide destructive affordances.
Source
Thrown at autogpt_platform/backend/backend/api/features/v1.py:2783
tags=["skills"],
dependencies=[Security(requires_user)],
)
async def delete_copilot_skill(
user_id: Annotated[str, Security(get_user_id)],
name: str = Path(..., description="Slug of the skill to delete"),
) -> dict[str, str]:
"""Delete a user-distilled skill by slug.
Built-in defaults are not user-deletable — attempting to delete one
returns 400. Missing skills return 404 so the UI can reconcile a
stale list.
"""
try:
slug = await delete_user_skill(user_id, name)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
except BuiltInSkillError as exc:
raise HTTPException(status_code=400, detail=str(exc))
except SkillNotFoundError as exc:
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail=str(exc))
return {"name": slug}
########################################################
##################### API KEY ##############################
########################################################
@v1_router.post(
"/api-keys",
summary="Create new API key",
tags=["api-keys"],
dependencies=[Security(requires_user)],
)
async def create_api_key(
request: CreateAPIKeyRequest,View on GitHub (pinned to 9c8bb5550f)
Solutions
- Filter deletes with the is_default flag from the skill detail/list payload.
- If the default is unwanted in the UI, hide it client-side — deletion is intentionally blocked server-side.
- Operators wanting default sets changed must change the packaged default skills, not per-user deletes.
Example fix
// before
{skills.map(s => <DeleteButton onClick={() => api.deleteSkill(s.name)} />)}
// after
{skills.map(s => !s.isDefault && <DeleteButton onClick={() => api.deleteSkill(s.name)} />)} Defensive patterns
Strategy: type-guard
Validate before calling
const detail = await api.getSkillDetail(slug);
if (detail.isDefault) { show('Built-in skills cannot be deleted'); return; } Type guard
function isDeletableSkill(s: {isDefault?: boolean}): boolean {
return s.isDefault !== true;
} Try / catch
try {
await api.deleteSkill(slug);
} catch (e) {
if (e.status === 400 && /built-in/i.test(e.detail)) { hideDeleteUiFor(slug); return; }
throw e;
} Prevention
- Hide delete affordances for entries with is_default=true.
- Don't run blanket delete loops over mixed default+user skill lists.
- Filter defaults out of user-management views.
When it happens
Trigger: DELETE /skills/{name} where name matches a built-in default skill slug (the same slugs get_default_skill_with_body resolves).
Common situations: UIs rendering a delete button on every list row including defaults; scripts iterating the full skill list and deleting each entry; users attempting to remove unwanted default skills to declutter.
Related errors
- Skill content rejected by virus scan
- name is required
- Failed to download skill (HTTP ${res.status})
- start and end query params are required
- str(exc)
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/a58fb3398be99d8e.
Report an issue: GitHub.