{"record":{"id":"802822ce62da58c3","repo":"jackwener/OpenCLI","slug":"createlist-failed-errors-0-message-json-str","errorCode":null,"errorMessage":"CreateList failed: ${errors[0].message || JSON.stringify(errors[0])}","messagePattern":"CreateList failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/list-create.js","lineNumber":58,"sourceCode":"function requireCreateListResult(result, expectedName, expectedMode) {\n    if (!result || typeof result !== 'object') {\n        throw new CommandExecutionError(`Unexpected result from twitter list-create: ${JSON.stringify(result)}`);\n    }\n    if (result.httpStatus === 401 || result.httpStatus === 403) {\n        throw new AuthRequiredError('x.com', `Twitter CreateList returned HTTP ${result.httpStatus}`);\n    }\n    if (!result.ok) {\n        const snippet = String(result.bodyText || '').slice(0, 300);\n        throw new CommandExecutionError(`HTTP ${result.httpStatus} from CreateList: ${snippet}`);\n    }\n    if (!result.bodyJson || typeof result.bodyJson !== 'object') {\n        throw new CommandExecutionError(`CreateList returned malformed JSON payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);\n    }\n    const list = result.bodyJson?.data?.list;\n    if (!list || typeof list !== 'object') {\n        const errors = result.bodyJson?.errors;\n        if (Array.isArray(errors) && errors.length > 0) {\n            throw new CommandExecutionError(`CreateList failed: ${errors[0].message || JSON.stringify(errors[0])}`);\n        }\n        throw new CommandExecutionError(`CreateList returned no list payload. Body: ${String(result.bodyText || '').slice(0, 300)}`);\n    }\n    const id = String(list.id_str || list.id || '');\n    if (!/^\\d+$/.test(id)) {\n        throw new CommandExecutionError('CreateList returned a list payload without a numeric list id.');\n    }\n    if (typeof list.name !== 'string' || !list.name.trim()) {\n        throw new CommandExecutionError('CreateList returned a list payload without a list name.');\n    }\n    if (list.name.trim() !== expectedName) {\n        throw new CommandExecutionError(`CreateList returned name ${JSON.stringify(list.name)}, expected ${JSON.stringify(expectedName)}.`);\n    }\n    const modeValue = typeof list.mode === 'string' ? list.mode : '';\n    if (!modeValue) {\n        throw new CommandExecutionError('CreateList returned a list payload without list mode.');\n    }\n    const mode = /private/i.test(modeValue) ? 'private' : 'public';","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/list-create.js#L40-L76","documentation":"This CommandExecutionError is thrown by requireCreateListResult in clis/twitter/list-create.js:58 when the CreateList response is valid JSON with ok status, but contains no data.list object and instead carries a GraphQL errors array. The library surfaces errors[0].message (or its JSON) verbatim. It means Twitter's GraphQL layer rejected the mutation even though the HTTP transport succeeded.","triggerScenarios":"Response shape { errors: [ { message: ... } ] } with no data.list: e.g. schema DecodeException from a features/variables mismatch with the queryId schema, authorization/GraphQL-level denial, or duplicate/invalid list parameters rejected at the GraphQL layer.","commonSituations":"A newer x.com client expects different `features` than the hardcoded FEATURES map (strato DecodeException); the hardcoded queryId no longer matches the features schema; the account lacks permission to create lists (restricted/suspended); duplicate list name constraints enforced GraphQL-side.","solutions":["Read the surfaced errors[0].message — it names the actual GraphQL failure (e.g. DecodeException names the offending field).","If it is a DecodeException, update FEATURES in clis/twitter/list-create.js to exactly match the current web client's CreateList feature set (extra/unknown features are rejected).","Ensure CREATE_LIST_QUERY_ID and FEATURES come from the same web client version — a mismatched pair triggers schema errors.","Check the account can create lists (not suspended/restricted) and the name/description satisfy Twitter's constraints.","Retry once before debugging deeply — Twitter sometimes returns non-fatal transient error arrays; the library itself checks for a valid list first, so a fatal throw here is a real rejection."],"exampleFix":"// before (features drift vs current schema)\nconst FEATURES = { responsive_web_graphql_timeline_navigation_enabled: true, ... };\n// after (capture the exact features payload from a live CreateList request in the browser devtools)\nconst FEATURES = { /* current exact feature set from live x.com request */ };","handlingStrategy":"validation","validationCode":"// Pre-validate what the GraphQL layer most commonly rejects:\nconst name = String(kwargs.name || '').trim();\nif (!name || name.length > 25) throw new Error('invalid list name');\nif (String(kwargs.description || '').trim().length > 100) throw new Error('description too long');\nif (!['public','private'].includes(String(kwargs.mode||'public').toLowerCase())) throw new Error('invalid mode');","typeGuard":"function hasGraphqlErrors(bodyJson) {\n  return Array.isArray(bodyJson?.errors) && bodyJson.errors.length > 0;\n}","tryCatchPattern":"try {\n  const row = await opencli twitter list-create name;\n} catch (err) {\n  if (/^CreateList failed:/.test(err.message)) {\n    const reason = err.message.slice('CreateList failed:'.length).trim();\n    if (/DecodeException|decode/i.test(reason)) updateQueryIdAndFeatures();\n    else reportFatal(reason);\n  } else throw err;\n}","preventionTips":["Keep CREATE_LIST_QUERY_ID and FEATURES captured from the same web client version — mismatched pairs cause DecodeException","Do not add extra/unknown feature flags; Twitter rejects requests with an unexpected features schema","Confirm the account is in good standing and allowed to create lists","Remember Twitter can return non-fatal errors arrays alongside a created list — the library already checks for a valid list first"],"tags":["graphql","twitter","api-error","response-parsing"],"backgroundTag":"graphql-errors-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}