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

  1. Use the cursor exactly as returned by the previous `list`/page response — do not construct or edit it manually.
  2. URL-encode the cursor when embedding it in a query string and decode it once on receipt.
  3. Verify the client didn't truncate the cursor (they can be long); check request logs for the full value.
  4. 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

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


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