{"record":{"id":"07d4e09a995afae5","repo":"jackwener/OpenCLI","slug":"failed-to-add-username-to-list-listid-no-m","errorCode":null,"errorMessage":"Failed to add @${username} to list ${listId}: no member_count in response","messagePattern":"Failed to add @(.+?) to list (.+?): no member_count in response","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/list-add-core.js","lineNumber":71,"sourceCode":"\nexport function buildListAddMemberRow({ addResult, memberCountBefore, listId, username, userId }) {\n    if (!addResult?.httpOk) {\n        throw new CommandExecutionError(\n            `Failed to add @${username} to list ${listId}: HTTP ${addResult?.status ?? 0}${addResult?.fetchError ? ' (' + addResult.fetchError + ')' : ''}${addResult?.raw ? ' — ' + addResult.raw : ''}`\n        );\n    }\n\n    // X often returns a partial GraphQL error on `default_banner_media_results`\n    // even on successful mutations. Treat only missing main data or non-decode\n    // GraphQL errors as command failures.\n    const hasMemberCount = addResult.mc !== null && addResult.mc !== undefined;\n    const fatalErrors = fatalGraphqlErrors(addResult.errors);\n    if (!hasMemberCount && fatalErrors.length) {\n        const msg = fatalErrors.map((e) => e.message || JSON.stringify(e)).join('; ');\n        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: ${msg.slice(0, 300)}`);\n    }\n    if (!hasMemberCount) {\n        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: no member_count in response`);\n    }\n\n    const memberCountAfter = Number(addResult.mc);\n    if (!Number.isFinite(memberCountAfter)) {\n        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: invalid member_count in response`);\n    }\n\n    if (memberCountAfter < memberCountBefore) {\n        throw new CommandExecutionError(\n            `Failed to add @${username} to list ${listId}: member_count decreased unexpectedly (${memberCountBefore} → ${memberCountAfter})`\n        );\n    }\n\n    const countIncreased = memberCountAfter > memberCountBefore;\n    const noop = !countIncreased;\n    if (noop && addResult.isMember !== true) {\n        throw new CommandExecutionError(\n            `Failed to add @${username} to list ${listId}: member_count unchanged and membership was not confirmed`","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/list-add-core.js#L53-L89","documentation":"A CommandExecutionError from buildListAddMemberRow thrown when the add-member response contains neither a member_count nor any fatal GraphQL errors. The library uses member_count as its success signal, so an absent count means the mutation's outcome cannot be verified and the command is treated as failed.","triggerScenarios":"addResult.mc is null/undefined, fatalGraphqlErrors() returns empty, and HTTP was ok — X returned a success-shaped but structurally unexpected payload (schema drift or a non-mutation response).","commonSituations":"X changing the GraphQL response shape (version drift); hitting an unexpected page/redirect that returned HTML parsed as an empty payload; a bot-checked response stripped of data.","solutions":["Update this library to the latest version to pick up fixes for X's current response schema.","Retry after a short wait — intermittent bot-check pages can produce empty payloads.","Refresh session cookies; a logged-out or challenged session may receive degraded responses.","Inspect the raw response (enable debug logging) to confirm what X actually returned and file an issue if the schema changed."],"exampleFix":"// before: outdated library parses old schema\nawait listAddUser(page, { listId: '123456789', username: 'alice' });\n// after\nnpm update <this-cli-package>  # then rerun the list-add command","handlingStrategy":"retry","validationCode":"null","typeGuard":"function hasVerifiableMemberCount(r) {\n  return r?.mc !== null && r?.mc !== undefined;\n}","tryCatchPattern":"let lastErr;\nfor (let i = 0; i < 3; i++) {\n  try { return await listAddUser(page, { listId, username }); }\n  catch (e) {\n    if (!/no member_count in response/.test(e.message)) throw e;\n    lastErr = e;\n    await sleep(5000 * (i + 1));\n  }\n}\nthrow lastErr;","preventionTips":["Keep the library updated — schema drift on X's side is the usual cause.","Refresh cookies to avoid bot-challenge pages that return degraded payloads.","Retry transient failures with backoff.","Enable raw response logging to capture payloads for bug reports."],"tags":["twitter","graphql","schema-drift","cli"],"backgroundTag":"missing-field-in-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}