mastra-ai/mastra · error · HTTPException
Could not derive skill ID from name. Please provide an expli
Error message
Could not derive skill ID from name. Please provide an explicit id.
What it means
This 400 is thrown when neither an explicit `id` was provided in the request body nor could `toSlug(name)` produce a non-empty ID, i.e. the handler cannot determine an identifier for the new stored skill. It guards against inserting records with empty/undefined IDs. The library asks the caller to supply the ID explicitly.
Source
Thrown at packages/server/src/server/handlers/stored-skills.ts:329
visibility: bodyVisibility,
}) => {
try {
const storage = mastra.getStorage();
if (!storage) {
throw new HTTPException(500, { message: 'Storage is not configured' });
}
const skillStore = await storage.getStore('skills');
if (!skillStore) {
throw new HTTPException(500, { message: 'Skills storage domain is not available' });
}
// Derive ID from name if not explicitly provided
const id = providedId || toSlug(name);
if (!id) {
throw new HTTPException(400, {
message: 'Could not derive skill ID from name. Please provide an explicit id.',
});
}
// Check if skill with this ID already exists
const existing = await skillStore.getById(id);
if (existing) {
throw new HTTPException(409, { message: `Skill with id ${id} already exists` });
}
// Force authorId from the authenticated caller; ignore any body-provided value.
// No owner = always public (no auth / no user context).
// With an owner, respect the client's choice, defaulting to 'private'.
const authorId = getCallerAuthorId(requestContext) ?? undefined;
const visibility: 'private' | 'public' = authorId ? (bodyVisibility ?? 'private') : 'public';
// Derive references/scripts/assets path arrays from the files tree
// so agents can discover them via skill_read even when only `files` is provided.View on GitHub (pinned to 75dd419e61)
Solutions
- Provide an explicit `id` in the request body (kebab-case string)
- Send a non-empty, meaningful `name` that can be slugified into an ID
- Validate name/id client-side before calling the API and reject empty payloads
- If generating IDs programmatically, fall back to a UUID/slug when the name is unusable
Example fix
// before
await fetch('/api/stored-skills', { method: 'POST', body: JSON.stringify({ name: '***' }) });
// after
await fetch('/api/stored-skills', { method: 'POST', body: JSON.stringify({ id: 'my-skill', name: 'My Skill' }) }); Defensive patterns
Strategy: validation
Validate before calling
function assertValidSkillInput(body: { id?: string; name?: string }) {
const id = body.id ?? toSlug(body.name ?? '');
if (!id) throw new Error('Provide an explicit id or a non-empty slugifiable name');
return id;
} Type guard
function hasDerivableId(b: { id?: string; name?: string }): b is { id: string; name?: string } {
return typeof b.id === 'string' && b.id.length > 0;
} Try / catch
try {
await createStoredSkill(body);
} catch (e) {
if (String((e as Error).message).includes('derive skill ID')) {
// retry with an explicit id
await createStoredSkill({ ...body, id: body.id ?? crypto.randomUUID() });
return;
}
throw e;
} Prevention
- Always send an explicit `id` for programmatic creates
- Validate `name` is non-empty and contains slugifiable characters client-side
- Strip/replace punctuation-only names before submission
- Add a form-level required check for name or id
When it happens
Trigger: POST /api/stored-skills with an empty or missing `name` (e.g. `""` or whitespace-only) and no `id` field; a name made entirely of characters that `toSlug` strips out, yielding an empty string; omitting both fields from the JSON payload.
Common situations: Client form allows submitting an empty skill name; programmatic callers send `{}` or a name of only punctuation/emoji that slugifies to nothing; API migration where `id` was previously auto-generated server-side.
Related errors
- Could not derive MCP client ID from name. Please provide an
- Could not derive scorer definition ID from name. Please prov
- Worker input exceeds inputLimitBytes (${data.byteLength} > $
- bad request: ${responseText}
- GitHub pull requests require an owner/repository source.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8a9f14c852fa297d.
Report an issue: GitHub.