jackwener/OpenCLI · error · CommandExecutionError
CreateList returned a list payload without a numeric list id
Error message
CreateList returned a list payload without a numeric list id.
What it means
This CommandExecutionError is thrown by requireCreateListResult in clis/twitter/list-create.js:64 when the returned list object exists but lacks an id that matches /^\d+$/. Twitter list ids are numeric (id_str or id); the library requires one to hand back a usable listId. It protects callers from using a malformed or missing identifier.
Source
Thrown at clis/twitter/list-create.js:64
}
if (!result.ok) {
const snippet = String(result.bodyText || '').slice(0, 300);
throw new CommandExecutionError(`HTTP ${result.httpStatus} from CreateList: ${snippet}`);
}
if (!result.bodyJson || typeof result.bodyJson !== 'object') {
throw new CommandExecutionError(`CreateList returned malformed JSON payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);
}
const list = result.bodyJson?.data?.list;
if (!list || typeof list !== 'object') {
const errors = result.bodyJson?.errors;
if (Array.isArray(errors) && errors.length > 0) {
throw new CommandExecutionError(`CreateList failed: ${errors[0].message || JSON.stringify(errors[0])}`);
}
throw new CommandExecutionError(`CreateList returned no list payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);
}
const id = String(list.id_str || list.id || '');
if (!/^\d+$/.test(id)) {
throw new CommandExecutionError('CreateList returned a list payload without a numeric list id.');
}
if (typeof list.name !== 'string' || !list.name.trim()) {
throw new CommandExecutionError('CreateList returned a list payload without a list name.');
}
if (list.name.trim() !== expectedName) {
throw new CommandExecutionError(`CreateList returned name ${JSON.stringify(list.name)}, expected ${JSON.stringify(expectedName)}.`);
}
const modeValue = typeof list.mode === 'string' ? list.mode : '';
if (!modeValue) {
throw new CommandExecutionError('CreateList returned a list payload without list mode.');
}
const mode = /private/i.test(modeValue) ? 'private' : 'public';
if (mode !== expectedMode) {
throw new CommandExecutionError(`CreateList returned mode ${mode}, expected ${expectedMode}.`);
}
return { createdList: list, listId: id, listMode: mode };
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Log/inspect the full list payload (the error deliberately omits it) to see which id fields Twitter actually returned.
- If Twitter changed the field name/format, update the extraction in clis/twitter/list-create.js:62 (currently `list.id_str || list.id`) to the new field.
- Verify you are talking to the real x.com API and not a stub/mock environment returning non-numeric ids.
- Check whether the list exists on x.com and, if created, retrieve its numeric id from the UI or a ListLatest/ListByRequest query.
- Retry creation only after confirming no list was actually created, to avoid duplicates.
Example fix
// before const id = String(list.id_str || list.id || ''); // after (if Twitter adds a new id field) const id = String(list.id_str || list.id || list.rest_id || '');
Defensive patterns
Strategy: type-guard
Validate before calling
// Guard the id fields before trusting the returned list id:
function hasNumericListId(list) {
const id = String(list?.id_str || list?.id || '');
return /^\d+$/.test(id);
} Type guard
function hasNumericListId(list) {
const raw = list && (list.id_str ?? list.id);
return typeof raw === 'string' || typeof raw === 'number'
? /^\d+$/.test(String(raw))
: false;
} Try / catch
try {
const row = await opencli twitter list-create name;
} catch (err) {
if (/without a numeric list id/.test(err.message)) {
// inspect the raw payload / verify the list on x.com; do not use a fabricated id
reportFatal('CreateList returned a list without a usable numeric id');
} else throw err;
} Prevention
- Only trust numeric ids (id_str/id) from CreateList; never persist cursor-style or encoded ids as list identifiers
- Update the id extraction path promptly if Twitter renames or reformats the id field
- Test against the real x.com API — mock servers returning stub ids will trip this guard
- Verify on x.com whether the list exists before re-running creation to avoid duplicates
When it happens
Trigger: data.list present but both id_str and id are missing, null, non-numeric (e.g. a base64 GraphQL cursor-style id), or empty string — typically a response schema change or a partially populated list object.
Common situations: Twitter changing CreateList to return a different id field name or format; a mock/test server returning a stub list without numeric ids; future GraphQL versions returning string-encoded ids instead of numeric id_str.
Related errors
- Twitter UserMedia returned malformed user result
- Twitter UserMedia returned malformed timeline instructions
- Malformed Twitter follower: missing screen_name
- CreateList returned no list payload. Body: ${String(result.b
- ${probe.detail}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b2339c2359a788f2.
Report an issue: GitHub.