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

  1. Delete one or more existing skills (DELETE /skills/{name}) then retry the upload.
  2. If updating an existing skill, reuse its exact name so the upsert path applies rather than adding a new entry.
  3. 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

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


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/47e5a8512b9726c5. Report an issue: GitHub.