{"record":{"id":"031ea07c4093ad16","repo":"jackwener/OpenCLI","slug":"twitter-collection-username-must-be-a-valid-twitte","errorCode":null,"errorMessage":"twitter collection username must be a valid Twitter/X handle","messagePattern":"twitter collection username must be a valid Twitter/X handle","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/twitter/user-timeline.js","lineNumber":170,"sourceCode":"}\n\nexport async function resolveUserTimelineContext(\n    page,\n    rawUsername,\n    { allowLoggedInDefault = false, commandName = 'tweets' } = {},\n) {\n    const raw = String(rawUsername ?? '').trim();\n    let username = normalizeTwitterScreenName(raw);\n    if (raw && !username) {\n        throw new ArgumentError(\n            `twitter ${commandName} username must be a valid Twitter/X handle`,\n            commandName === 'collection'\n                ? 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z'\n                : 'Example: opencli twitter tweets @jack --limit 20',\n        );\n    }\n    if (!username && !allowLoggedInDefault) {\n        throw new ArgumentError('twitter collection username must be a valid Twitter/X handle', 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z');\n    }\n    if (!username) {\n        await page.goto('https://x.com/home');\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const href = unwrapBrowserResult(await page.evaluate(`() => {\n            const link = document.querySelector('a[data-testid=\"AppTabBar_Profile_Link\"]');\n            return link ? link.getAttribute('href') : null;\n        }`));\n        if (!href || typeof href !== 'string') {\n            throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');\n        }\n        username = normalizeTwitterScreenName(href);\n        if (!username) {\n            throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');\n        }\n    }\n\n    const cookies = await page.getCookies({ url: 'https://x.com' });","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/user-timeline.js#L152-L188","documentation":"This is the same validation as the generic handle error but on the branch where no username was provided at all and `allowLoggedInDefault` is false for the `collection` command: `resolveUserTimelineContext` throws an ArgumentError because there is no valid handle and no permission to fall back to the logged-in user. The collection command requires either an explicit handle or an enabled logged-in default.","triggerScenarios":"Running `opencli twitter collection` (or invoking resolveUserTimelineContext with `allowLoggedInDefault: false`) with an empty/missing username argument, so `username` is '' after normalization.","commonSituations":"Forgetting the positional username on the collection command; a shell variable expanding to empty (`$USER` unset); calling the shared helper programmatically without passing `allowLoggedInDefault: true`; confusing collection with `tweets`, which may allow the logged-in default.","solutions":["Provide a handle explicitly: `opencli twitter collection @jack --until 2026-07-23T00:00:00Z`.","Ensure the shell variable holding the username is non-empty before invoking.","If a logged-in default is intended, call resolveUserTimelineContext with `allowLoggedInDefault: true` (and have an active x.com session) so the profile link is used.","Double-check the subcommand usage with --help to see whether it requires a username."],"exampleFix":"// before\nopencli twitter collection --until 2026-07-23T00:00:00Z        // missing username\n// after\nopencli twitter collection @jack --until 2026-07-23T00:00:00Z","handlingStrategy":"validation","validationCode":"// collection requires an explicit handle unless allowLoggedInDefault is set\nif (!username && !allowLoggedInDefault) {\n  throw new Error('twitter collection requires a username, e.g. opencli twitter collection @jack --until 2026-07-23T00:00:00Z');\n}","typeGuard":"function canResolveCollectionContext(args) {\n  const hasHandle = /^[A-Za-z0-9_]{1,15}$/.test(String(args.username ?? '').trim().replace(/^@/, ''));\n  return hasHandle || args.allowLoggedInDefault === true;\n}","tryCatchPattern":"try {\n  await cli.run(['twitter', 'collection', username, '--until', until]);\n} catch (e) {\n  if (/must be a valid Twitter\\/X handle/.test(e.message) && !username) {\n    console.error('Username is required for collection; pass @handle or enable the logged-in default');\n  } else throw e;\n}","preventionTips":["Always include the username for twitter collection.","Guard shell variables ($USER etc.) for emptiness before substitution.","When calling the helper programmatically, set allowLoggedInDefault only if a browser session exists.","Check subcommand --help to confirm which commands require a username."],"tags":["argument-validation","twitter","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}