Significant-Gravitas/AutoGPT · warning · HTTPException
Skill limit reached ({MAX_USER_SKILLS}). Delete an unused sk
Error message
Skill limit reached ({MAX_USER_SKILLS}). Delete an unused skill first. What it means
Skill-upload returns 409 when `store_user_skill` raises SkillLimitError: the authenticated user already has MAX_USER_SKILLS user-distilled skills stored. The cap is per-user and counted before the upsert, so even overwriting an existing slug counts against the limit path when the cap is already reached.
Source
Thrown at autogpt_platform/backend/backend/api/features/v1.py:2692
if parsed is None:
raise HTTPException(
status_code=400,
detail=(
"File is not a valid SKILL.md — expected YAML frontmatter with "
"'name' and 'description' followed by a markdown body."
),
)
try:
stored = await store_user_skill(
user_id,
name=parsed.name,
description=parsed.description,
body=parsed.body,
triggers=list(parsed.triggers),
version=parsed.version,
)
except SkillLimitError as exc:
raise HTTPException(status_code=409, detail=str(exc))
except (VirusDetectedError, VirusScanError) as exc:
logger.warning("[skills] virus scan rejected uploaded skill: %s", exc)
raise HTTPException(
status_code=400, detail="Skill content rejected by virus scan"
)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return CopilotSkillInfo(
name=stored.name,
description=stored.description,
triggers=list(stored.triggers),
)
@v1_router.get(
path="/skills/{name}",
summary="Read a single copilot skill with its full SKILL.md body",
operation_id="readCopilotSkill",View on GitHub (pinned to 9c8bb5550f)
Solutions
- Delete one or more existing skills (DELETE /skills/{name}) then retry the upload.
- If updating an existing skill, reuse its exact name so the upsert path applies rather than adding a new entry.
- Operators: raise MAX_USER_SKILLS if the product allows, but treat it as a resource cap to respect.
Defensive patterns
Strategy: try-catch
Validate before calling
const skills = await api.listSkills();
if (skills.length >= MAX_USER_SKILLS) {
show('Skill limit reached — delete an unused skill first');
return;
} Try / catch
try {
await api.uploadSkill(content);
} catch (e) {
if (e.status === 409) { promptSkillDeletion(); return; }
throw e;
} Prevention
- Show remaining skill quota in the UI before upload attempts.
- Reuse existing skill names to update via upsert instead of accumulating new entries.
- Bulk-upload pipelines should check the cap and handle 409 explicitly.
When it happens
Trigger: POST upload of a new SKILL.md by a user whose stored skill count equals MAX_USER_SKILLS (the message interpolates the numeric cap, e.g. 'Skill limit reached (25)').
Common situations: Power users accumulating distilled copilot skills; automated pipelines bulk-uploading skills per user; test accounts that repeatedly upload unique-named skills.
Related errors
- Failed to download skill (HTTP ${res.status})
- str(exc)
- No user found with the provided email.
- Either user_id or email query parameter is required.
- Failed to reset usage
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/47e5a8512b9726c5.
Report an issue: GitHub.