mastra-ai/mastra · error
Attention read-all response is missing its continuation curs
Error message
Attention read-all response is missing its continuation cursor.
What it means
markAllFactoryAttentionRead pages through the attention read-all endpoint; when a page reports hasMore=true but omits nextCursor, the continuation cursor needed to keep marking items read is missing, so it throws rather than silently stopping or looping forever. This is a strict server-response invariant check against inconsistent API responses.
Source
Thrown at mastracode/factory-ui/src/ui/domains/factory/services/attention.ts:111
item: FactoryAttentionItem,
action: FactoryAttentionReceiptAction,
): Promise<{ receipt: { key: string; state: 'read' | 'archived'; readAt: string; archivedAt: string | null } }> {
return requestJson(
`${baseUrl}/web/factory/projects/${encodeURIComponent(factoryProjectId)}/attention/${item.kind}/${encodeURIComponent(attentionItemSourceId(item))}/${item.occurrence}/${action}`,
{ method: 'POST' },
);
}
export async function markAllFactoryAttentionRead(baseUrl: string, factoryProjectId: string): Promise<{ ok: true }> {
let before: string | undefined;
while (true) {
const query = before ? `?before=${encodeURIComponent(before)}` : '';
const page = await requestJson<{ ok: true; hasMore: boolean; nextCursor?: string }>(
`${baseUrl}/web/factory/projects/${encodeURIComponent(factoryProjectId)}/attention/read-all${query}`,
{ method: 'POST' },
);
if (!page.hasMore) return { ok: true };
if (!page.nextCursor) throw new Error('Attention read-all response is missing its continuation cursor.');
before = page.nextCursor;
}
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Inspect the raw read-all response confirming hasMore=true with no nextCursor; report/fix the server to always return nextCursor when hasMore is true.
- Align frontend and API versions (deploy both together).
- Check for any response-transforming middleware/proxy stripping fields.
- As a caller, catch and surface the error; re-running markAll after the server fix resumes marking items read.
Example fix
// before (server)
return Response.json({ ok: true, hasMore: true });
// after (server)
return Response.json({ ok: true, hasMore: true, nextCursor: oldestUnreadTs }); Defensive patterns
Strategy: try-catch
Validate before calling
if (page.hasMore && typeof page.nextCursor !== 'string') throw new Error('Response cursor invariant violated'); Type guard
function isReadAllPage(v: unknown): v is { ok: true; hasMore: boolean; nextCursor?: string } {
if (typeof v !== 'object' || v === null) return false;
const o = v as Record<string, unknown>;
return o.ok === true && typeof o.hasMore === 'boolean' && (o.nextCursor === undefined || typeof o.nextCursor === 'string');
} Try / catch
try {
await markAllFactoryAttentionRead(baseUrl, projectId);
} catch (e) {
showToast('Could not mark all as read; some items may remain unread.');
console.error(e); // invariant violation: server sent hasMore without nextCursor
} Prevention
- Enforce server-side: nextCursor is always present when hasMore is true.
- Deploy client and API pagination changes together.
- Integration-test the read-all pagination loop.
When it happens
Trigger: POST /web/factory/projects/:id/attention/read-all?before=... returns { ok:true, hasMore:true } without nextCursor — server bug, version skew between client expectations and API, or a proxy altering the response body.
Common situations: API deployed with pagination behavior changed while the frontend expects the old contract; gateway/response transform stripping optional fields; partial rollout where the endpoint version differs from the client.
Related errors
- Query parameter "status" must be "draft" or "published"
- Invalid audit event response
- Invalid audit portal response
- Token rotation returned incomplete data
- App creation returned incomplete data
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/27fdbf491493e6ab.
Report an issue: GitHub.