jackwener/OpenCLI · error · CommandExecutionError

Failed to add @${username} to list ${listId}: invalid member

Error message

Failed to add @${username} to list ${listId}: invalid member_count in response

What it means

A CommandExecutionError from buildListAddMemberRow thrown when the member_count in the response exists but Number(addResult.mc) is not finite (NaN). This guards against malformed or non-numeric count values that would make post-mutation verification meaningless.

Source

Thrown at clis/twitter/list-add-core.js:76

        );
    }

    // X often returns a partial GraphQL error on `default_banner_media_results`
    // even on successful mutations. Treat only missing main data or non-decode
    // GraphQL errors as command failures.
    const hasMemberCount = addResult.mc !== null && addResult.mc !== undefined;
    const fatalErrors = fatalGraphqlErrors(addResult.errors);
    if (!hasMemberCount && fatalErrors.length) {
        const msg = fatalErrors.map((e) => e.message || JSON.stringify(e)).join('; ');
        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: ${msg.slice(0, 300)}`);
    }
    if (!hasMemberCount) {
        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: no member_count in response`);
    }

    const memberCountAfter = Number(addResult.mc);
    if (!Number.isFinite(memberCountAfter)) {
        throw new CommandExecutionError(`Failed to add @${username} to list ${listId}: invalid member_count in response`);
    }

    if (memberCountAfter < memberCountBefore) {
        throw new CommandExecutionError(
            `Failed to add @${username} to list ${listId}: member_count decreased unexpectedly (${memberCountBefore} → ${memberCountAfter})`
        );
    }

    const countIncreased = memberCountAfter > memberCountBefore;
    const noop = !countIncreased;
    if (noop && addResult.isMember !== true) {
        throw new CommandExecutionError(
            `Failed to add @${username} to list ${listId}: member_count unchanged and membership was not confirmed`
        );
    }
    const verifiedBy = `member_count ${memberCountBefore} → ${memberCountAfter}`;
    return {
        listId,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — a transient bad response often succeeds on a second attempt.
  2. Update the library to match X's current response schema.
  3. Refresh session cookies to avoid bot-check/degraded responses.
  4. Enable raw-response logging to inspect what value mc held, and report persistent occurrences.

Example fix

// before
{ mc: "unknown" }  // Number('unknown') === NaN -> throws
// after: retry with a fresh session, expecting numeric mc
{ mc: 42 }
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

function hasNumericMemberCount(r) {
  return typeof r?.mc === 'number' && Number.isFinite(r.mc) || (typeof r?.mc === 'string' && /^\d+$/.test(r.mc));
}

Try / catch

try {
  return await listAddUser(page, { listId, username });
} catch (e) {
  if (/invalid member_count/.test(e.message)) {
    await sleep(5000);
    return listAddUser(page, { listId, username }); // one retry, often transient
  }
  throw e;
}

Prevention

When it happens

Trigger: X returned a member_count value that cannot be coerced to a finite number — e.g. a string like 'unknown', null-adjacent placeholder, or a corrupted/HTML response parsed into the mc field.

Common situations: Response scraping picking up markup instead of the count during X UI changes; schema drift producing unexpected types at addResult.mc.

Related errors


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