mastra-ai/mastra · warning · MastraError
OBSERVABILITY_INVALID_DELTA_CURSOR
OBSERVABILITY_INVALID_DELTA_CURSOR
Error message
Invalid observability delta cursor
What it means
decodeDeltaCursor validates the string form of an observability delta cursor: it must be all digits. A cursor failing the /^\d+$/ regex (empty string, letters, base64 blob, negative sign) indicates corruption or a cursor produced by a different mechanism, so this USER-category error is thrown.
Source
Thrown at packages/core/src/storage/domains/observability/inmemory.ts:223
const cursorId = cursorIds.get(previous);
cursorIds.delete(previous);
records[existingIndex] = record;
if (cursorId !== undefined) {
cursorIds.set(record, cursorId);
}
return;
}
records.push(record);
cursorIds.set(record, this.allocateObservabilityCursorId());
}
private encodeDeltaCursor(cursorId?: number | null): string {
return (cursorId ?? 0).toString();
}
private decodeDeltaCursor(cursor: string): number {
if (!/^\d+$/.test(cursor)) {
throw new MastraError({
id: 'OBSERVABILITY_INVALID_DELTA_CURSOR',
domain: ErrorDomain.MASTRA_OBSERVABILITY,
category: ErrorCategory.USER,
text: 'Invalid observability delta cursor',
});
}
const cursorId = Number.parseInt(cursor, 10);
if (!Number.isInteger(cursorId) || cursorId < 0) {
throw new MastraError({
id: 'OBSERVABILITY_INVALID_DELTA_CURSOR',
domain: ErrorDomain.MASTRA_OBSERVABILITY,
category: ErrorCategory.USER,
text: 'Invalid observability delta cursor',
});
}
return cursorId;View on GitHub (pinned to 75dd419e61)
Solutions
- Only pass cursors obtained from a previous response of the same storage instance; never hand-construct them.
- Reset the poller's cursor (start from the beginning / undefined cursor) when an invalid cursor is detected.
- Validate cursor format before sending if cursors cross process/serialization boundaries (e.g. base64-encoded payloads).
- Clear stale cursor state in your job/store if the backend was switched or the format changed.
Example fix
// before
const page = await storage.listMetrics({ cursor: lastCursor ?? 'abc' }); // throws
// after
const page = await storage.listMetrics({ cursor: isValidNumericCursor(lastCursor) ? lastCursor : undefined }); Defensive patterns
Strategy: validation
Validate before calling
const isValidDeltaCursor = (c: unknown): c is string => typeof c === 'string' && /^\d+$/.test(c); if (cursor !== undefined && !isValidDeltaCursor(cursor)) cursor = undefined; // restart from beginning
Type guard
function isValidDeltaCursor(c: unknown): c is string {
return typeof c === 'string' && /^\d+$/.test(c);
} Try / catch
try {
page = await storage.listLogs({ cursor });
} catch (e) {
if ((e as MastraError).id === 'OBSERVABILITY_INVALID_DELTA_CURSOR') {
cursor = undefined;
page = await storage.listLogs({}); // reset cursor, restart polling
} else throw e;
} Prevention
- Only reuse cursors verbatim from the same storage provider's responses.
- Never persist cursors through transformations that can alter format.
- Clear stored cursor state when switching storage backends.
- Validate cursor strings before sending them across service boundaries.
When it happens
Trigger: Calling afterCursorId (directly or via a delta-polling list method) with a malformed cursor string — empty, non-numeric, truncated, or from another storage backend's cursor format.
Common situations: Persisting cursors to a store/file and mangling them; passing a cursor from a different provider (DB cursors are not numeric strings); hand-crafting cursors in tests or scripts; stale clients after a cursor format change.
Related errors
- Invalid knowledge node cursor.
- OBSERVABILITY_MISSING_RECORD_ID
- CursorSDKAgent resumeData must include a message.
- CursorSDKAgent resumeData.agentId must be a string when prov
- CursorSDKAgent does not support structuredOutput because the
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4566b31100cfe907.
Report an issue: GitHub.