Significant-Gravitas/AutoGPT · error · HTTPException

Skill '{slug}' not found

Error message

Skill '{slug}' not found

What it means

Skill-detail endpoint returns 404 when the slug (name path parameter, strip().lower()-ed) matches no built-in default AND `read_user_skill_with_body(user_id, slug)` returns None — i.e. the authenticated user has no stored user-distilled skill with that slug. Defaults are checked first, so this branch means specifically 'not a default and not one of your skills'.

Source

Thrown at autogpt_platform/backend/backend/api/features/v1.py:2746

    except OSError:
        # Don't leak the on-disk path; operators trace via server logs.
        logger.exception("[skills] failed to load default skill body for %s", slug)
        raise HTTPException(
            status_code=500,
            detail="Failed to load default skill body",
        )
    if default is not None:
        return CopilotSkillDetail(
            name=default.name,
            description=default.description,
            triggers=list(default.triggers),
            body=default.body,
            is_default=True,
        )

    parsed = await read_user_skill_with_body(user_id, slug)
    if parsed is None:
        raise HTTPException(
            status_code=HTTP_404_NOT_FOUND, detail=f"Skill '{slug}' not found"
        )
    sibling_files = await list_user_skill_sibling_paths(user_id, slug)
    return CopilotSkillDetail(
        name=parsed.name,
        description=parsed.description,
        triggers=list(parsed.triggers),
        body=parsed.body,
        version=parsed.version,
        is_default=False,
        sibling_files=sibling_files,
    )


@v1_router.delete(
    path="/skills/{name}",
    summary="Delete a user-distilled copilot skill",
    operation_id="deleteCopilotSkill",

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Re-fetch the skill list and only open details for slugs present in it (exact lowercase form).
  2. Normalize client-side: slug = name.trim().toLowerCase() before requesting.
  3. Remember user skills are per-user — another user's skill slug will 404 for you; defaults are shared.

Example fix

// before
const detail = await api.getSkill(rawName);
// after
const slug = rawName.trim().toLowerCase();
const detail = await api.getSkill(slug);
Defensive patterns

Strategy: type-guard

Validate before calling

const skills = await api.listSkills();
const target = skills.find(s => s.name === slug);
if (!target) { refreshSkillList(); return; }

Type guard

function isKnownSkillSlug(slug: string, known: {name: string}[]): boolean {
  return known.some(s => s.name === slug.trim().toLowerCase());
}

Try / catch

try {
  return await api.getSkillDetail(slug);
} catch (e) {
  if (e.status === 404) { await refreshSkillList(); return null; }
  throw e;
}

Prevention

When it happens

Trigger: GET /skills/{name} with a typo'd slug, a slug of another user's skill, or a slug deleted by the user (or overwritten) before the detail fetch.

Common situations: Expand-to-view dialogs opened from a stale skill list after deletion elsewhere; case/whitespace mismatches (slug is lowercased and trimmed server-side, callers sending CamelCase or padded slugs); links shared between users where skills are per-user.

Related errors


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