mastra-ai/mastra · error · HTTPException
Item not found in dataset: ${itemId}
Error message
Item not found in dataset: ${itemId} What it means
The LIST_ITEM_VERSIONS route (GET /datasets/:datasetId/items/:itemId/history) returns the SCD-2 history rows for an item. Because getItemHistory looks up rows by itemId globally, the handler verifies the first returned row's datasetId matches the path's datasetId; if it doesn't, the item exists but belongs to a different dataset, so a 404 is raised rather than leaking the item's existence in another dataset.
Source
Thrown at packages/server/src/server/handlers/datasets.ts:1135
export const LIST_ITEM_VERSIONS_ROUTE = createRoute({
method: 'GET',
path: '/datasets/:datasetId/items/:itemId/history',
responseType: 'json',
pathParamSchema: datasetAndItemIdPathParams,
responseSchema: listItemVersionsResponseSchema,
summary: 'Get item history',
description: 'Returns the full SCD-2 history of the item across all dataset versions',
tags: ['Datasets'],
requiresAuth: true,
handler: async ({ mastra, datasetId, itemId }) => {
assertDatasetsAvailable();
try {
const ds = await mastra.datasets.get({ id: datasetId });
const rows = await ds.getItemHistory({ itemId });
// Check rows belong to this dataset
if (rows.length > 0 && rows[0]?.datasetId !== datasetId) {
throw new HTTPException(404, { message: `Item not found in dataset: ${itemId}` });
}
return { history: rows };
} catch (error) {
if (error instanceof MastraError) {
throw new HTTPException(getHttpStatusForMastraError(error.id) as StatusCode, { message: error.message });
}
return handleError(error, 'Error listing item history');
}
},
});
export const GET_ITEM_VERSION_ROUTE = createRoute({
method: 'GET',
path: '/datasets/:datasetId/items/:itemId/versions/:datasetVersion',
responseType: 'json',
pathParamSchema: datasetItemVersionPathParams,
responseSchema: datasetItemResponseSchema.nullable(),
summary: 'Get item at specific dataset version',View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the itemId actually belongs to the datasetId in the request path (list items via GET /datasets/:datasetId/items and cross-check).
- Fix a mixed-up datasetId/itemId pair in the client code or saved configuration.
- If the item was moved or the dataset recreated, use the new dataset's ID or re-add the item.
- Ensure you're pointing at the correct Mastra server/deployment (IDs may differ across environments).
Example fix
// before
await fetch(`/api/datasets/${wrongDatasetId}/items/${itemId}/history`);
// after
const items = await fetch(`/api/datasets/${datasetId}/items`).then(r => r.json());
if (!items.items.some(i => i.id === itemId)) throw new Error('item not in this dataset');
await fetch(`/api/datasets/${datasetId}/items/${itemId}/history`); Defensive patterns
Strategy: try-catch
Validate before calling
const items = await fetch(`/api/datasets/${datasetId}/items?perPage=100`).then(r => r.json());
if (!items.items.some(i => i.id === itemId)) {
throw new Error(`Item ${itemId} does not belong to dataset ${datasetId}`);
} Type guard
function isItemInDataset(history: Array<{ datasetId: string }>, datasetId: string): boolean {
return history.length === 0 || history[0]?.datasetId === datasetId;
} Try / catch
try {
const res = await fetch(`/api/datasets/${datasetId}/items/${itemId}/history`);
if (res.status === 404) {
console.warn(`Item ${itemId} not in dataset ${datasetId}; verify IDs`);
return null;
}
if (!res.ok) throw new Error(await res.text());
return await res.json();
} catch (err) {
console.error('listItemVersions failed', err);
throw err;
} Prevention
- Always source itemId and datasetId from the same API response so they can't drift apart.
- Keep a client-side map of datasetId -> itemIds and check membership before cross-dataset calls.
- After recreating a dataset, invalidate cached item IDs.
- Log the full URL on 404s to quickly spot mixed-up path parameters.
When it happens
Trigger: Call GET /api/datasets/:datasetId/items/:itemId/history with an itemId that exists in some dataset but not the one named in the path. getItemHistory returns rows whose datasetId differs from the path datasetId.
Common situations: Copy-pasting an itemId from one dataset while calling against another datasetId in the URL; stale cached IDs after a dataset was re-created with a new ID; multi-tenant setups where two datasets contain items with the same itemId.
Related errors
- Item not found: ${itemId}
- Model "${modelId}" is not available. Available models: ${ids
- ACP connection is not initialized
- Model "${this.options.model}" is not available. Available mo
- ClaudeSDKAgent resumeData must include either sessionId or c
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/815e69758c5e03c1.
Report an issue: GitHub.