mastra-ai/mastra · error · Error
Invalid knowledge node cursor.
Error message
Invalid knowledge node cursor.
What it means
`parseKnowledgeNodeCursor` decodes and JSON-parses a pagination cursor and throws this generic message when parsing fails (JSON.parse error) or the result is not a plain object. Cursors are opaque tokens produced by the library; this error signals a malformed or hand-edited cursor. There are two throw sites — this one covers the parse/shape failure.
Source
Thrown at packages/core/src/storage/domains/knowledge/base.ts:189
name: node.name,
id: node.id,
namePrefix: filters.namePrefix?.toLocaleLowerCase() ?? null,
kind: filters.kind ?? null,
hasContent: filters.hasContent ?? null,
}),
);
}
/** @experimental Knowledge APIs are experimental and may change without notice. */
export function parseKnowledgeNodeCursor(
cursor: string,
filters: { namePrefix?: string; kind?: string; hasContent?: boolean },
): KnowledgeNodeCursor {
let value: unknown;
try {
value = JSON.parse(decodeURIComponent(cursor));
} catch {
throw new Error('Invalid knowledge node cursor.');
}
if (!value || typeof value !== 'object') throw new Error('Invalid knowledge node cursor.');
const parsed = value as Record<string, unknown>;
const updatedAt = typeof parsed.updatedAt === 'string' ? new Date(parsed.updatedAt) : new Date(Number.NaN);
if (
parsed.version !== 1 ||
parsed.type !== 'node' ||
typeof parsed.name !== 'string' ||
typeof parsed.id !== 'string' ||
Number.isNaN(updatedAt.getTime()) ||
parsed.namePrefix !== (filters.namePrefix?.toLocaleLowerCase() ?? null) ||
parsed.kind !== (filters.kind ?? null) ||
parsed.hasContent !== (filters.hasContent ?? null)
) {
throw new Error('Knowledge node cursor does not match the active browse filters.');
}
return { updatedAt, name: parsed.name, id: parsed.id };
}View on GitHub (pinned to 75dd419e61)
Solutions
- Use the cursor exactly as returned by the previous `list`/page response — do not construct or edit it manually.
- URL-encode the cursor when embedding it in a query string and decode it once on receipt.
- Verify the client didn't truncate the cursor (they can be long); check request logs for the full value.
- On this error, restart pagination from the beginning (omit the cursor) instead of retrying the same token.
Example fix
// before
const cursor = rows[0].someField; // wrong field / hand-made
const page = await listNodes({ cursor });
// after
const page1 = await listNodes({});
const page2 = await listNodes({ cursor: page1.nextCursor }); // opaque token reused verbatim Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeCursor(raw: unknown): raw is string {
if (typeof raw !== 'string' || raw.length === 0) return false;
try {
const decoded = JSON.parse(decodeURIComponent(raw));
return typeof decoded === 'object' && decoded !== null;
} catch {
return false;
}
} Type guard
function isValidNodeCursor(raw: unknown): raw is string {
if (!looksLikeCursor(raw)) return false;
try {
const v = JSON.parse(decodeURIComponent(raw as string)) as Record<string, unknown>;
return v.version === 1 && v.type === 'node' && typeof v.name === 'string' && !Number.isNaN(new Date(v.updatedAt as string).getTime());
} catch {
return false;
}
} Try / catch
try {
await listNodes({ cursor });
} catch (e) {
if (e instanceof Error && e.message === 'Invalid knowledge node cursor.') {
// restart pagination from the beginning
return listNodes({});
}
throw e;
} Prevention
- Treat cursors as opaque: never parse, edit, or construct them.
- URL-encode cursors in query strings and decode exactly once.
- Avoid storing cursors through layers that may truncate or re-escape characters.
- Validate cursor presence/shape client-side before sending requests.
When it happens
Trigger: Passing a cursor string that is not URL-encoded JSON (e.g. raw text, empty string, HTML from a bad link), or a value that decodes to a non-object (number, string, null).
Common situations: Client truncating the cursor in a URL query parameter; a proxy or framework decoding/re-encoding it incorrectly; storing cursors in a system that mangles special characters (%, {); hand-rolling a cursor instead of using the one returned by the previous page.
Related errors
- Knowledge node cursor does not match the active browse filte
- GitHub cursor must be a positive page number.
- perPage must be >= 0
- page must be >= 0
- page value too large
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/913bccb78969bc25.
Report an issue: GitHub.