jackwener/OpenCLI · error · CommandExecutionError

List ${listId} not found among your lists (${listsBefore.len

Error message

List ${listId} not found among your lists (${listsBefore.length} lists fetched).

What it means

Before deleting, list-delete fetches all of the user's managed lists and looks for one whose id matches listId. If no list matches, it throws CommandExecutionError with a count of how many lists were fetched, so you know the fetch succeeded but the ID is not among your lists. This prevents attempting to delete a list the account does not own.

Source

Thrown at clis/twitter/list-delete.js:110

        }

        await page.goto('https://x.com');
        await page.wait(3);
        const cookies = await page.getCookies({ url: 'https://x.com' });
        const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
        if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');

        const headers = JSON.stringify({
            'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
            'X-Csrf-Token': ct0,
            'X-Twitter-Auth-Type': 'OAuth2Session',
            'X-Twitter-Active-User': 'yes',
        });

        const listsBefore = await getManagedLists(page, headers);
        const targetList = listsBefore.find((list) => list.id === listId);
        if (!targetList) {
            throw new CommandExecutionError(`List ${listId} not found among your lists (${listsBefore.length} lists fetched).`);
        }

        await page.goto(`https://x.com/i/lists/${listId}`);
        await page.wait({ selector: '[data-testid="primaryColumn"]' });
        const deleteResult = unwrapBrowserResult(await page.evaluate(`(async () => {
            const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
            const visible = (el) => !!el && el.offsetParent !== null;
            const buttonText = (el) => (el.innerText || el.textContent || '').trim();
            const waitFor = async (fn, { timeoutMs = 10000, intervalMs = 200 } = {}) => {
                const started = Date.now();
                while (Date.now() - started < timeoutMs) {
                    const value = fn();
                    if (value) return value;
                    await sleep(intervalMs);
                }
                return null;
            };
            const findButton = (text) => Array.from(document.querySelectorAll('button, [role="button"]'))

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run `twitter list-manage` to list your owned lists and confirm the correct numeric ID
  2. Check whether the list was already deleted; re-run and treat this as a no-op if so
  3. Verify you own the list (you can only delete lists you created, not ones you follow)
  4. If you own many lists, check pagination in getManagedLists to ensure all lists were fetched

Example fix

// before
opencli twitter list-delete 999999999999 --confirm true
// after
opencli twitter list-manage        # find the real numeric id
opencli twitter list-delete 123456789 --confirm true
Defensive patterns

Strategy: validation

Validate before calling

const lists = await getManagedLists(page, headers);
const target = lists.find((l) => String(l.id) === String(listId));
if (!target) throw new Error(`List ${listId} not owned by this account; aborting delete`);

Type guard

function findOwnedList(lists, listId) {
  return (Array.isArray(lists) ? lists : []).find((l) => String(l?.id) === String(listId)) || null;
}

Try / catch

try {
  await runListDelete(page, kwargs);
} catch (e) {
  if (/not found among your lists/.test(e.message)) {
    console.error('Verify the ID via `twitter list-manage` — the list may be deleted or not owned by you.');
  } else throw e;
}

Prevention

When it happens

Trigger: listsBefore.find((list) => list.id === listId) returns undefined — the ID belongs to another user's list, was already deleted, is a list you follow but don't own, or the ID string mismatches (leading zeros/format).

Common situations: Deleting a list that was already removed in another session; typos or stale IDs in scripts; confusing owned lists with subscribed lists; the ListsManagement fetch returning only the first page of lists so a later-page list is missing.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/ddcbfa6ecdc485ee. Report an issue: GitHub.