mastra-ai/mastra · error · Error

Item ${id} does not belong to dataset ${datasetId}

Error message

Item ${id} does not belong to dataset ${datasetId}

What it means

Thrown by the in-memory dataset store when deleting an item whose current (live) SCD-2 row belongs to a different dataset than the one passed in. It means the item id exists but is not a member of the target datasetId, so the delete is refused to prevent cross-dataset mutation.

Source

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

    // T3.11
    await this.createDatasetVersion(args.datasetId, newVersion);

    return toDatasetItem(newRow);
  }

  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

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the item's datasetId (getItem) and pass the dataset the item actually belongs to.
  2. Check you haven't swapped datasetId and id in the call arguments.
  3. If the item was re-created elsewhere, delete using the id returned by the create/batchInsert call in that dataset.
  4. If the item is already deleted, note deleteItem silently no-ops instead of throwing; only ownership mismatch throws.

Example fix

// before
await storage.datasets.deleteItem({ datasetId: 'ds-b', id: itemId });
// after
const item = await storage.datasets.getItem({ datasetId: 'ds-a', id: itemId });
await storage.datasets.deleteItem({ datasetId: item.datasetId, id: itemId });
Defensive patterns

Strategy: validation

Validate before calling

const item = await storage.datasets.getItem({ datasetId, id });
if (!item) throw new Error(`Item ${id} not found in dataset ${datasetId}`);

Type guard

function belongsToDataset(item: { datasetId: string } | null, datasetId: string): item is { datasetId: string } {
  return item !== null && item.datasetId === datasetId;
}

Try / catch

try {
  await storage.datasets.deleteItem({ datasetId, id });
} catch (e) {
  if (String(e).includes('does not belong to dataset')) {
    // wrong dataset — resolve the owning dataset and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling storage.datasets.deleteItem({ datasetId, id }) with a valid item id that was created in a different dataset; passing a swapped datasetId/id pair; reusing a stale item reference after the item was moved or re-created in another dataset.

Common situations: Copy-paste of ids across datasets in tests or scripts; iterating a mixed list of item ids against one datasetId; client cache holding items from a previous dataset version.

Related errors


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