mastra-ai/mastra · error

FilesystemSkillsStorage: skill with id ${id} not found

Error message

FilesystemSkillsStorage: skill with id ${id} not found

What it means

FilesystemSkillsStorage.update first loads the skill by id and throws when no skill file matching that id exists on disk. Update is not upsert: you can only update skills that were previously created in the filesystem storage directory.

Source

Thrown at packages/core/src/storage/domains/skills/filesystem.ts:76

    const versionId = crypto.randomUUID();
    await this.createVersion({
      id: versionId,
      skillId: skill.id,
      versionNumber: 1,
      ...snapshotConfig,
      changedFields: Object.keys(snapshotConfig),
      changeMessage: 'Initial version',
    });

    return structuredClone(entity);
  }

  async update(input: StorageUpdateSkillInput): Promise<StorageSkillType> {
    const { id, ...updates } = input;

    const existing = await this.helpers.getById(id);
    if (!existing) {
      throw new Error(`FilesystemSkillsStorage: skill with id ${id} not found`);
    }

    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',
      'instructions',

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Create the skill first (or use an upsert pattern: check getById, then create if missing).
  2. Verify the id is correct and exists via getById/getList before updating.
  3. Confirm the filesystem storage is configured with the correct base directory / env vars so the skill file is visible.
  4. Restore the missing skill file or re-seed skills in the target directory.

Example fix

// before
await storage.update({ id: 'my-skill', status: 'active' }); // throws if missing
// after
const existing = await storage.getById('my-skill');
if (!existing) {
  await storage.create({ skill: { id: 'my-skill', ...defaults } });
}
await storage.update({ id: 'my-skill', status: 'active' });
Defensive patterns

Strategy: validation

Validate before calling

const existing = await storage.getById(id);
if (!existing) throw new Error(`skill ${id} does not exist; create it first`);

Type guard

async function skillExists(storage: FilesystemSkillsStorage, id: string): Promise<boolean> {
  return (await storage.getById(id)) != null;
}

Try / catch

try {
  return await storage.update(input);
} catch (e) {
  if (e instanceof Error && e.message.includes('not found')) {
    return storage.create({ skill: { ...input, ...defaults } as StorageCreateSkillInput });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling update({ id, ... }) for an id that was never created, was deleted, or whose backing file is missing/renamed on disk; a typo'd or stale id from another environment.

Common situations: Pointing storage at a different base directory than where skills were created (env misconfiguration); id mismatch after a rename or re-seed; calling update before create in a setup script.

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/58fe2b32ee507c17. Report an issue: GitHub.