{"record":{"id":"2f6141da98d01ce4","repo":"jackwener/OpenCLI","slug":"createlist-returned-no-list-payload-body-strin","errorCode":null,"errorMessage":"CreateList returned no list payload. Body: ${String(result.bodyText || '').slice(0, 300)}","messagePattern":"CreateList returned no list payload\\. Body: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/list-create.js","lineNumber":60,"sourceCode":"        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';\n    if (mode !== expectedMode) {\n        throw new CommandExecutionError(`CreateList returned mode ${mode}, expected ${expectedMode}.`);","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/list-create.js#L42-L78","documentation":"This CommandExecutionError is thrown by requireCreateListResult in clis/twitter/list-create.js:60 when the CreateList response is ok JSON but lacks a data.list object and contains no errors array either. The library requires bodyJson.data.list to exist to confirm the list was created. This indicates an unexpected/empty success payload from Twitter.","triggerScenarios":"Response like { data: {} }, { data: { list: null } }, or an empty JSON object with HTTP 2xx — a successful transport but no list entity returned, e.g. the mutation silently failed or Twitter changed the CreateList response shape (renamed/moved data.list).","commonSituations":"Twitter changing the GraphQL response schema (data.list moved or renamed), silent server-side failure returning empty data, response intercepted/modified by browser extensions or automation scripts, partial responses from a degraded Twitter backend.","solutions":["Inspect the embedded Body snippet to see what Twitter actually returned in place of data.list.","Check whether the list was actually created on x.com (the mutation can succeed server-side while returning an unexpected payload) before retrying to avoid duplicates.","If the response shape changed, update requireCreateListResult to read the new path for the created list object.","Retry after a short delay if Twitter's backend was degraded — an empty data payload can be transient.","Disable browser extensions/scripts that might rewrite fetch responses inside the automated page."],"exampleFix":"// before (old response path)\nconst list = result.bodyJson?.data?.list;\n// after (if Twitter moved the created entity in the response)\nconst list = result.bodyJson?.data?.list ?? result.bodyJson?.data?.create_list;","handlingStrategy":"validation","validationCode":"// After the call, guard the expected response shape:\nfunction hasListPayload(result) {\n  const list = result?.bodyJson?.data?.list;\n  return Boolean(list && typeof list === 'object');\n}","typeGuard":"function isCreatedListPayload(bodyJson) {\n  return Boolean(\n    bodyJson && typeof bodyJson === 'object' &&\n    bodyJson.data && typeof bodyJson.data === 'object' &&\n    bodyJson.data.list && typeof bodyJson.data.list === 'object'\n  );\n}","tryCatchPattern":"try {\n  const row = await opencli twitter list-create name;\n} catch (err) {\n  if (/returned no list payload/.test(err.message)) {\n    // check x.com whether the list was actually created before retrying\n    const exists = await checkListExistsOnX(name);\n    if (!exists) retryCreationOnce();\n  } else throw err;\n}","preventionTips":["Check x.com for the list before retrying — the mutation may have succeeded server-side despite the empty payload, and a blind retry creates duplicates","Watch for Twitter response schema changes to data.list and update the extraction path","Disable browser extensions that rewrite fetch responses in the automated page","Avoid running bulk creations while Twitter is degraded (empty data payloads can be transient)"],"tags":["graphql","twitter","response-parsing","schema-change"],"backgroundTag":"missing-api-response-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}