{"record":{"id":"e69082ba56890336","repo":"jackwener/OpenCLI","slug":"list-listid-not-found-among-your-lists","errorCode":null,"errorMessage":"List ${listId} not found among your lists.","messagePattern":"List (.+?) not found among your lists\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/list-remove-core.js","lineNumber":99,"sourceCode":"            return d.data?.user?.result?.rest_id || null;\n        }`));\n        if (!userId) throw new CommandExecutionError(`Could not resolve user @${username}`);\n\n        // Resolve listId → name so we can match the dialog row.\n        const listsQueryId = await resolveTwitterQueryId(page, 'ListsManagementPageTimeline', LISTS_MANAGEMENT_QUERY_ID);\n        const listsUrl = `/i/api/graphql/${listsQueryId}/ListsManagementPageTimeline?features=${encodeURIComponent(JSON.stringify(LISTS_MANAGEMENT_FEATURES))}`;\n        const listsData = unwrapBrowserResult(await page.evaluate(`async () => {\n            const r = await fetch(${JSON.stringify(listsUrl)}, { headers: ${headers}, credentials: 'include' });\n            if (!r.ok) return { __error: 'HTTP ' + r.status };\n            return await r.json();\n        }`));\n        if (listsData && listsData.__error) {\n            throw new CommandExecutionError(`Could not fetch lists: ${listsData.__error}`);\n        }\n        const parsedLists = parseListsManagement(listsData, new Set());\n        const targetList = parsedLists.find((l) => l.id === listId);\n        if (!targetList) {\n            throw new CommandExecutionError(`List ${listId} not found among your lists.`);\n        }\n        const targetName = targetList.name;\n\n        await page.goto(`https://x.com/${username}`);\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const uiResult = unwrapBrowserResult(await page.evaluate(`(async () => {\n            const sleep = (ms) => new Promise(r => setTimeout(r, ms));\n            const findOne = (sel, root = document) => root.querySelector(sel);\n            const waitFor = async (fn, { timeoutMs = 8000, intervalMs = 200 } = {}) => {\n                const t0 = Date.now();\n                while (Date.now() - t0 < timeoutMs) { const v = fn(); if (v) return v; await sleep(intervalMs); }\n                return null;\n            };\n            try {\n                if (!window.__opencliListMutations) {\n                    window.__opencliListMutations = [];\n                    const origFetch = window.fetch.bind(window);\n                    window.fetch = async function(...args) {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/list-remove-core.js#L81-L117","documentation":"The ListsManagementPageTimeline fetch succeeded, but after parsing with parseListsManagement no list in the timeline has an id equal to the requested listId. The library throws this CommandExecutionError because it can only operate on lists visible in the user's lists-management timeline.","triggerScenarios":"Calling twitter list-remove with a listId that does not exist, belongs to another user, was deleted, or is a list the account owns but that does not appear on the first ListsManagementPageTimeline page (many lists, pagination not followed). Also triggered when parseListsManagement fails to recognize a changed timeline schema.","commonSituations":"Passing a list slug (e.g. 'my-list') instead of the numeric ID; using a list ID copied from a list the user follows but does not own; the list was deleted elsewhere; the account has so many lists that the target is beyond the first page; Twitter changed the timeline response shape so parseListsManagement returns an empty set.","solutions":["Verify the listId is the numeric ID of a list the logged-in account owns (x.com/i/lists/<id>), not a slug or someone else's list.","Look up the correct numeric ID via the lists UI or ListsManagementPageTimeline and retry with it.","If the account owns many lists, ensure pagination is followed or reduce list count so the target appears in the first timeline page.","If parseListsManagement returns nothing for a valid response, update its parser to the current ListsManagementPageTimeline schema.","Confirm the list still exists (it may have been deleted)."],"exampleFix":"// before (slug instead of numeric id)\nawait cli.run('twitter list-remove', { listId: 'my-cool-list', username: '@bob' });\n// after\nawait cli.run('twitter list-remove', { listId: '1718345678901234567', username: '@bob' }); // numeric owned-list id","handlingStrategy":"validation","validationCode":"// Ensure listId is numeric and the list is one you own before calling\nif (!/^\\d+$/.test(listId)) throw new Error(`listId must be numeric, got: ${listId}`);\nconst owned = await fetchOwnedLists(); // via x.com/i/lists UI or API\nif (!owned.some(l => l.id === listId)) throw new Error(`List ${listId} is not an owned list`);","typeGuard":"function isOwnedList(parsedLists, listId) {\n  return Array.isArray(parsedLists) && parsedLists.some(l => String(l.id) === String(listId));\n}","tryCatchPattern":"try {\n  await listRemoveUser(page, { listId, username });\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.includes('not found among your lists')) {\n    // re-enumerate owned lists and pick the correct numeric id\n  } else throw e;\n}","preventionTips":["Always pass the numeric list ID, never the slug.","Confirm the list is owned by (not merely followed by) the logged-in account.","Check the list still exists before running removals in bulk.","Keep the lists parser updated if you own many lists (pagination)."],"tags":["twitter","lists","invalid-argument","pagination"],"backgroundTag":"resource-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}