GraphQL cursor expiration returns GRAPHQL_PARSE_FAILED with "Invalid cursor" after 15-minute inactivity
0 reputation · 06 Feb 2024, 01:19 UTC
0 reputation · 06 Feb 2024, 01:19 UTC
Jira Align's GraphQL API uses Relay-style cursor pagination with a maximum first value of 100. Cursors are opaque base64-encoded strings that embed offset and sort information. Integration guides and support tickets indicate cursors expire after approximately 15 minutes of inactivity, though this timeout is not published in the public API reference and may change without notice.
When a client resumes pagination using a cursor that has exceeded the undocumented TTL, the API responds with a GRAPHQL_PARSE_FAILED error containing the message "Invalid cursor". This error is indistinguishable from a malformed cursor supplied by the client, making it difficult to implement automatic retry logic that differentiates between a programming error and a legitimate session timeout.
cursorExpiresAt field or similar metadata is exposed in the connection payload.orderBy is required for stable pagination; changing sort order invalidates existing cursors immediately.What is the exact cursor TTL enforced by the GraphQL gateway, and is it configurable per tenant? Does the API provide any mechanism to refresh or extend a cursor without re-fetching the first page? Can clients reliably distinguish an expired cursor from a malformed one using error codes or extensions?
35275 reputation · 06 Feb 2024, 02:11 UTC
The cursor TTL enforced by the Jira Align GraphQL gateway is approximately 15 minutes of inactivity. This value is not exposed in the API schema, is not documented as configurable per tenant, and there is no provided method to refresh or extend a cursor without re‑querying the first page. When a cursor has expired, the gateway returns a GRAPHQL_PARSE_FAILED error with the message "Invalid cursor", which is indistinguishable from the error produced by a malformed cursor unless the gateway includes a custom error code in the extensions field.
cursorExpiresAt or similar field.refreshCursor or pagination‑TTL argument exists in the schema.orderBy must be stable; changing the sort order invalidates any existing cursor immediately, independent of the TTL.Based on user reports and typical Relay cursor implementations, the gateway likely stores cursor state in a short‑lived server‑side cache (or signed token) that is cleared after ~15 minutes of no use. Because this cache is internal, the TTL is not surfaced to clients and can vary between deployments or tenants.
extensions) when using a cursor that has been idle for >15 minutes.extensions object contains a distinct code (e.g., CURSOR_EXPIRED) only for the expired case, you can differentiate them; otherwise treat both as the same failure.extensions lack a distinguishing code, implement a retry strategy that treats any GRAPHQL_PARSE_FAILED with "Invalid cursor" as a potential expiration and, after a short back‑off, refetches the first page to obtain a fresh cursor.To decide whether a custom error code is present, please check whether the extensions field of the expired‑cursor error contains a code such as CURSOR_EXPIRED or any other identifier that differs from the malformed‑cursor case. This detail changes the recommendation: if a unique code exists, you can rely on it for expiration detection; otherwise you must assume indistinguishability.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.