mastra-ai/mastra · error · Error

Dataset not found: ${datasetId}

Error message

Dataset not found: ${datasetId}

What it means

Thrown after the ownership check when bumping the dataset version during deleteItem: the datasetId no longer resolves in the datasets map. The item row exists, but the parent dataset was deleted concurrently or never existed under that id.

Source

Thrown at packages/core/src/storage/domains/datasets/inmemory.ts:352

  }

  protected async _doDeleteItem({ id, datasetId }: DeleteDatasetItemInput): Promise<void> {
    const rows = this.db.datasetItems.get(id);
    if (!rows || rows.length === 0) {
      return; // no-op if item doesn't exist
    }

    const currentRow = rows.find(r => r.validTo === null && !r.isDeleted);
    if (!currentRow) {
      return; // already deleted
    }
    if (currentRow.datasetId !== datasetId) {
      throw new Error(`Item ${id} does not belong to dataset ${datasetId}`);
    }

    const dataset = this.db.datasets.get(datasetId);
    if (!dataset) {
      throw new Error(`Dataset not found: ${datasetId}`);
    }

    // Bump version (T3.26)
    const newVersion = dataset.version + 1;
    this.db.datasets.set(datasetId, { ...dataset, version: newVersion });

    // T3.9 — close old row
    currentRow.validTo = newVersion;

    // T3.9 — insert tombstone.
    // Tenancy is read from the prior current row rather than re-fetched from
    // the parent dataset (the pattern used by every DB adapter). This is
    // deliberate and safe: tenancy is immutable post-create on both datasets
    // and items (see CreateDatasetInput / UpdateDatasetInput in ../../types.ts),
    // so currentRow.organizationId / currentRow.projectId are guaranteed to
    // equal dataset.organizationId / dataset.projectId. Keep this branch in
    // sync with the DB adapters if that invariant ever changes.
    const now = new Date();

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Confirm the dataset exists first: dataset.get(datasetId) before deleting items.
  2. Reorder logic to delete items before deleting the dataset, or rely on cascade deletion of items.
  3. Refresh dataset/item ids after store restart — in-memory data does not persist.
  4. Serialize concurrent dataset mutations or guard with existence checks in your workflow.

Example fix

// before
await storage.datasets.deleteItem({ datasetId, id });
// after
const ds = await storage.datasets.get(datasetId);
if (ds) await storage.datasets.deleteItem({ datasetId, id });
Defensive patterns

Strategy: validation

Validate before calling

const ds = await storage.datasets.get(datasetId);
if (!ds) return; // dataset gone; skip item deletion

Type guard

null

Try / catch

try {
  await storage.datasets.deleteItem({ datasetId, id });
} catch (e) {
  if (String(e).startsWith('Dataset not found')) return; // idempotent cleanup
  throw e;
}

Prevention

When it happens

Trigger: deleteItem({ datasetId, id }) where the dataset was deleted between item creation and the delete call; a typo'd datasetId that happens to match a stale item row; concurrent deletion of the dataset from another request in the same process.

Common situations: Test teardown deleting datasets while cleanup code still deletes items; in-memory store restarted (data lost) while the caller cached old ids; race between dataset deletion and item deletion in async code.

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/40adf7073b11869e. Report an issue: GitHub.