{"record":{"id":"61576a06b581fbd3","repo":"jackwener/OpenCLI","slug":"describetwitterapierror-listsmanagementpagetimeli","errorCode":null,"errorMessage":"describeTwitterApiError('ListsManagementPageTimeline', data.error)","messagePattern":"describeTwitterApiError\\('ListsManagementPageTimeline', data\\.error\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/lists.js","lineNumber":166,"sourceCode":"                    } catch {}\n                }\n            } catch {}\n            return null;\n        }`);\n        const queryId = unwrap(queryIdRaw) || LISTS_QUERY_ID;\n        const headers = JSON.stringify({\n            'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,\n            'X-Csrf-Token': ct0,\n            'X-Twitter-Auth-Type': 'OAuth2Session',\n            'X-Twitter-Active-User': 'yes',\n        });\n        const apiUrl = buildUrl(queryId);\n        const data = await page.evaluate(`async () => {\n            const r = await fetch(${JSON.stringify(apiUrl)}, { headers: ${headers}, credentials: 'include' });\n            return r.ok ? await r.json() : { error: r.status };\n        }`);\n        if (data?.error) {\n            throw new CommandExecutionError(describeTwitterApiError('ListsManagementPageTimeline', data.error));\n        }\n        const seen = new Set();\n        if (!getListsManagementInstructions(data)) {\n            throw new CommandExecutionError('Twitter lists returned an unexpected payload shape');\n        }\n        const lists = parseListsManagement(data, seen);\n        if (lists.length === 0) {\n            throw new EmptyResultError('twitter lists', 'No owned or subscribed lists found');\n        }\n        return lists.slice(0, limit);\n    },\n});\n","sourceCodeStart":148,"sourceCodeEnd":179,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/lists.js#L148-L179","documentation":"The ListsManagementPageTimeline GraphQL call used to enumerate your lists returned an error payload ({error: status} from a non-OK fetch). The library converts it via describeTwitterApiError into a CommandExecutionError naming the GraphQL operation and status.","triggerScenarios":"The fetch of the lists-management API URL returned a non-OK status — 401/403 (session invalid), 400 (expired twitter-openapi queryId), 404 (endpoint removed), or 429 (rate limited) — and page.evaluate mapped it to {error: r.status}.","commonSituations":"Stale queryId fetched from the fa0311/twitter-openapi placeholder after X rotates GraphQL ids (HTTP 400); expired session cookies; rate limiting after repeated list commands; transient X API incidents.","solutions":["Read the status code in the thrown message; 400 → update the library so a fresh queryId is fetched from twitter-openapi","Re-login to x.com if the status is 401/403","Back off and retry on 429; reduce polling frequency","Retry later or check X API status on 5xx"],"exampleFix":"// before\nconst lists = await run('twitter', 'lists', { limit: 50 }); // throws on API error\n// after\ntry {\n  const lists = await run('twitter', 'lists', { limit: 50 });\n} catch (e) {\n  if (/400/.test(e.message)) console.error('queryId likely expired — update opencli/twitter-openapi.');\n  else if (/429/.test(e.message)) { await sleep(60000); return run('twitter', 'lists', { limit: 50 }); }\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"const cookies = await page.getCookies({ url: 'https://x.com' });\nif (!cookies.some(c => c.name === 'ct0')) throw new Error('Log into x.com first.');","typeGuard":"const apiErrored = (d) => d && typeof d === 'object' && 'error' in d;","tryCatchPattern":"try {\n  const lists = await run('twitter', 'lists', { limit: 50 });\n} catch (e) {\n  const m = /HTTP|\\b(\\d{3})\\b/.exec(e.message);\n  if (m && m[1] === '429') { await new Promise(r => setTimeout(r, 60000)); return run('twitter', 'lists', { limit: 50 }); }\n  if (m && m[1] === '400') { console.error('queryId expired — update opencli/twitter-openapi.'); }\n  throw e;\n}","preventionTips":["Keep the library updated — the queryId is fetched from twitter-openapi and X rotates it","Throttle command frequency to avoid 429s","Re-login on 401/403","Monitor for repeated identical statuses (X-side incident or expired queryId)"],"tags":["twitter-api","graphql-error","http-error"],"backgroundTag":"graphql-api-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}