mastra-ai/mastra · error

${this.name}: entity with id ${id} already exists

Error message

${this.name}: entity with id ${id} already exists

What it means

createEntity on a FilesystemVersioned store refuses to overwrite: it hydrates state from disk, and if an entity with the given id already exists in the in-memory map it throws instead of replacing it. This protects versioned entity data from silent data loss. Use update or upsert semantics instead of create for existing ids.

Source

Thrown at packages/core/src/storage/filesystem-versioned.ts:492

      }
    }

    return result;
  }

  // ==========================================================================
  // Entity CRUD
  // ==========================================================================

  async getById(id: string): Promise<TEntity | null> {
    this.hydrate();
    return this.entities.has(id) ? structuredClone(this.entities.get(id)!) : null;
  }

  async createEntity(id: string, entity: TEntity): Promise<TEntity> {
    this.hydrate();
    if (this.entities.has(id)) {
      throw new Error(`${this.name}: entity with id ${id} already exists`);
    }
    this.entities.set(id, structuredClone(entity));
    return structuredClone(entity);
  }

  async updateEntity(id: string, updates: Record<string, unknown>): Promise<TEntity> {
    this.hydrate();
    const existing = this.entities.get(id);
    if (!existing) {
      throw new Error(`${this.name}: entity with id ${id} not found`);
    }

    const updated = { ...existing } as Record<string, unknown>;

    for (const [key, value] of Object.entries(updates)) {
      if (key === 'id') continue;
      if (value === undefined) continue;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check existence first with get() or a getEntity call and switch to the update path when the id already exists.
  2. Generate a fresh unique id (uuid/nanoid) instead of reusing an id derived from user input.
  3. Delete the existing entity first if replacement is truly intended, then recreate.

Example fix

// before
await store.create('agents', { id: 'my-agent', ...data });
// after
const existing = await store.get('agents', 'my-agent');
if (existing) {
  await store.update('agents', 'my-agent', data);
} else {
  await store.create('agents', { id: 'my-agent', ...data });
}
Defensive patterns

Strategy: validation

Validate before calling

const existing = await store.get('entities', id);
if (existing) throw new Error(`Refusing to create: entity ${id} already exists`);

Try / catch

try {
  await store.create('entities', entity);
} catch (e) {
  if (String(e.message).includes('already exists')) {
    await store.update('entities', entity.id, entity);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling store.create('entities', entity) (which delegates to createEntity) with an id that already exists in the store; calling createEntity(id, entity) directly twice with the same id; a race where two requests create the same id concurrently after hydrate.

Common situations: Seeding scripts re-run without clearing storage; importing fixtures whose ids collide with existing data; retry logic that re-issues a create after a timeout even though the first write succeeded.

Related errors


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