{"record":{"id":"755ae5f0bf4e5387","repo":"jackwener/OpenCLI","slug":"twitter-usermedia-returned-malformed-user-result","errorCode":null,"errorMessage":"Twitter UserMedia returned malformed user result","messagePattern":"Twitter UserMedia returned malformed user result","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/download.js","lineNumber":245,"sourceCode":"function requireFetchPayload(value, context) {\n    const result = requireObjectPayload(unwrapBrowserResult(value), context);\n    if (result.ok === true) {\n        return result.payload;\n    }\n    if (result.ok === false) {\n        throwGraphqlFetchError(context, Number(result.status) || 0, typeof result.error === 'string' ? result.error : '');\n    }\n    throw new CommandExecutionError(`Twitter ${context} returned malformed fetch result`);\n}\n\nfunction requireUserMediaPayload(data) {\n    const payload = requireObjectPayload(data, 'UserMedia');\n    if (Array.isArray(payload.errors) && payload.errors.length > 0) {\n        throw new CommandExecutionError(`Twitter UserMedia returned GraphQL errors: ${JSON.stringify(payload.errors).slice(0, 200)}`);\n    }\n    const result = payload.data?.user?.result;\n    if (!result || typeof result !== 'object') {\n        throw new CommandExecutionError('Twitter UserMedia returned malformed user result');\n    }\n    const instructions = result.timeline_v2?.timeline?.instructions || result.timeline?.timeline?.instructions;\n    if (!Array.isArray(instructions)) {\n        throw new CommandExecutionError('Twitter UserMedia returned malformed timeline instructions');\n    }\n    return payload;\n}\n\nfunction parseUserMedia(data, seen) {\n    const items = [];\n    let nextCursor = null;\n    const result = requireUserMediaPayload(data).data.user.result;\n    const instructionSets = [\n        result.timeline_v2?.timeline?.instructions,\n        result.timeline?.timeline?.instructions,\n    ].filter(Array.isArray);\n    const instructions = instructionSets.flat();\n    const visit = (value) => {","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/download.js#L227-L263","documentation":"requireUserMediaPayload validates the UserMedia GraphQL response shape. After confirming there are no top-level errors, it requires payload.data.user.result to be a non-null object; if the user node is absent or null it throws 'malformed user result'. This guards against responses where Twitter returns no user entity for the requested screen name.","triggerScenarios":"The UserMedia response has data, data.user, or data.user.result missing/null — typically the screen name does not resolve to an existing account, or Twitter returned an empty user payload without a GraphQL errors array.","commonSituations":"Typo in the username or a renamed/deleted handle; passing '@' or empty after normalization; Twitter briefly returning incomplete payloads during incidents; endpoint schema changes moving the user node.","solutions":["Verify the handle is correct and currently exists on x.com (check in a browser).","Strip stray characters ('@', whitespace) — the CLI already trims and normalizes, but confirm the input.","Re-run later if Twitter is having an incident returning incomplete payloads.","Update the response parsing path if X changed the UserMedia response shape (data.user.result relocated)."],"exampleFix":"// before\nawait opencli twitter download @thisuserdoesnotexist12345 --limit 5\n// CommandExecutionError: Twitter UserMedia returned malformed user result\n\n// after: use a real handle\nawait opencli twitter download @jack --limit 5","handlingStrategy":"type-guard","validationCode":"// Confirm handle exists before invoking\nconst exists = await fetch('https://x.com/' + handle).then(r => r.status !== 404);\nif (!exists) throw new Error('Unknown handle: ' + handle);","typeGuard":"function hasUserResult(payload) {\n    return !!payload\n        && typeof payload === 'object'\n        && !!payload.data\n        && typeof payload.data.user?.result === 'object'\n        && payload.data.user.result !== null;\n}","tryCatchPattern":"try {\n    await twitterDownload(username);\n} catch (err) {\n    if (err instanceof CommandExecutionError && err.message.includes('malformed user result')) {\n        // treat as unknown/renamed handle: validate input and retry with corrected handle\n    } else throw err;\n}","preventionTips":["Validate the handle (strip '@', trim, check non-empty) before invoking the CLI","Confirm the account exists on x.com in a browser first","Watch for X schema migrations that relocate data.user.result","Treat this error as 'handle not found' and prompt for corrected input"],"tags":["twitter","graphql","api-response","schema-change"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}