mastra-ai/mastra · error
Skill with id ${id} not found
Error message
Skill with id ${id} not found What it means
In-memory skills storage update() looks up the skill by id in its map and throws when it is absent. Like create, update targets an existing record only — there is no upsert semantics.
Source
Thrown at packages/core/src/storage/domains/skills/inmemory.ts:98
changedFields: Object.keys(snapshotConfig),
changeMessage: 'Initial version',
});
} catch (error) {
// Roll back the orphaned skill record
this.db.skills.delete(skill.id);
throw error;
}
// Return the thin record
return this.deepCopyConfig(newConfig);
}
async update(input: StorageUpdateSkillInput): Promise<StorageSkillType> {
const { id, ...updates } = input;
const existingConfig = this.db.skills.get(id);
if (!existingConfig) {
throw new Error(`Skill with id ${id} not found`);
}
// Separate metadata fields from config fields
const { authorId, visibility, activeVersionId, status, ...rawConfigFields } = updates;
// Filter out undefined keys: callers may spread partial snapshots into
// update() and rely on "omit = no change" semantics. Without this, an
// undefined value would clobber the latest version's populated field
// when spread into newConfig below.
const configFields: Record<string, unknown> = {};
for (const [key, value] of Object.entries(rawConfigFields)) {
if (value !== undefined) configFields[key] = value;
}
// Config field names from StorageSkillSnapshotType
const configFieldNames = [
'name',
'description',View on GitHub (pinned to 75dd419e61)
Solutions
- Create the skill before updating, or switch to a persistent storage adapter if data must survive restarts.
- Check existence via a get/has call before updating and create if missing (upsert pattern).
- Verify the id against a list call; fix typos or stale ids.
- Re-seed the in-memory store at startup if updates depend on seeded data.
Example fix
// before
await skillsStorage.update({ id: 'deploy', status: 'active' }); // throws if absent
// after
if (!skillsDb.skills.has('deploy')) {
await skillsStorage.create({ skill: { id: 'deploy', ...defaults } });
}
await skillsStorage.update({ id: 'deploy', status: 'active' }); Defensive patterns
Strategy: validation
Validate before calling
const existing = await storage.get({ id });
if (!existing) throw new Error(`skill ${id} not found; create before update`); Type guard
async function skillExists(storage: InMemorySkillsStorage, id: string): Promise<boolean> {
return (await storage.get({ id })) != null;
} Try / catch
try {
return await storage.update(input);
} catch (e) {
if (e instanceof Error && e.message === `Skill with id ${input.id} not found`) {
return storage.create({ skill: { id: input.id, ...defaults, ...input } as StorageCreateSkillInput });
}
throw e;
} Prevention
- Check existence before updating, or implement upsert logic.
- Remember in-memory stores reset on process restart; re-seed or use persistent storage.
- Validate ids against a list call before issuing updates.
- Avoid reusing ids captured from prior sessions.
When it happens
Trigger: Calling update({ id, ... }) for an id never created in this store instance; updating on a fresh/restarted process where the in-memory data is gone; a typo'd or cross-environment id.
Common situations: In-memory store reset between dev-server restarts while the client still holds old ids; test isolation issues where setup didn't create the skill; id mismatch after data re-seed with new ids.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Agent with id ${id} not found
- Dataset not found: ${args.id}
- Dataset not found: ${args.datasetId}
- Item not found: ${args.id}
- MCP client with id ${id} not found
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/3f512db4c6b0b149.
Report an issue: GitHub.