{"record":{"id":"b1edb2987159d46a","repo":"jackwener/OpenCLI","slug":"twitter-profile-username-must-be-a-valid-twitter-x","errorCode":null,"errorMessage":"twitter profile username must be a valid Twitter/X handle","messagePattern":"twitter profile username must be a valid Twitter/X handle","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/twitter/profile.js","lineNumber":88,"sourceCode":"}\n\ncli({\n    site: 'twitter',\n    name: 'profile',\n    access: 'read',\n    description: 'Fetch a Twitter user profile — bio, stats, etc. (defaults to the logged-in user when no username is given)',\n    domain: 'x.com',\n    strategy: Strategy.COOKIE,\n    browser: true,\n    args: [\n        { name: 'username', type: 'string', positional: true, help: 'Twitter screen name (with or without @). Defaults to the logged-in user when omitted.' },\n    ],\n    columns: ['screen_name', 'name', 'bio', 'location', 'url', 'followers', 'following', 'tweets', 'likes', 'verified', 'created_at'],\n    func: async (page, kwargs) => {\n        const rawUsername = String(kwargs.username ?? '').trim();\n        let username = normalizeTwitterScreenName(rawUsername);\n        if (rawUsername && !username) {\n            throw new ArgumentError('twitter profile username must be a valid Twitter/X handle', 'Example: opencli twitter profile @jack');\n        }\n        // If no username, detect the logged-in user.\n        // Bridge wraps primitive page.evaluate returns as { session, data:<value> };\n        // unwrap so the href string is usable downstream.\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            username = normalizeTwitterScreenName(href);\n            if (!username)\n                throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');\n        }\n        // Navigate directly to the user's profile page (gives us cookie context)","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/profile.js#L70-L106","documentation":"ArgumentError thrown during argument validation when a username was supplied to `twitter profile` but it cannot be normalized into a valid Twitter/X handle by normalizeTwitterScreenName (empty after stripping @, illegal characters, too long).","triggerScenarios":"`opencli twitter profile <bad>` where the raw string (after trim) is non-empty but normalizeTwitterScreenName returns falsy: e.g. 'https://x.com/jack/path' passed raw, '@', names with spaces or >15 chars, or non-ASCII handles.","commonSituations":"Pasting a full profile URL instead of the handle; including a trailing slash or query string; accidental whitespace/newline from shell quoting; passing an email or display name instead of the handle.","solutions":["Pass just the handle: `opencli twitter profile @jack` or `jack` (the @ is optional)","If you have a profile URL, extract the path segment first (x.com/<handle> → <handle>)","Trim surrounding whitespace/quotes from the argument in your script/shell"],"exampleFix":"// before\nopencli twitter profile 'https://x.com/jack?foo=1'\n// after\nconst handle = new URL(url).pathname.split('/')[1];\nopencli twitter profile handle;","handlingStrategy":"validation","validationCode":"function normalizeHandle(raw) {\n  let h = String(raw ?? '').trim();\n  const m = h.match(/(?:x|twitter)\\.com\\/([A-Za-z0-9_]{1,15})/); // accept URLs\n  if (m) h = m[1];\n  h = h.replace(/^@/, '');\n  return /^[A-Za-z0-9_]{1,15}$/.test(h) ? h : null;\n}\nif (!normalizeHandle(input)) throw new Error('invalid Twitter handle');","typeGuard":null,"tryCatchPattern":"try {\n  await opencli('twitter profile', { username });\n} catch (e) {\n  if (e.name === 'ArgumentError' && /valid Twitter\\/X handle/.test(e.message)) {\n    throw new Error(`Bad handle \"${username}\" — use @name or a 1-15 char alphanumeric/underscore name`);\n  }\n  throw e;\n}","preventionTips":["Extract the handle from profile URLs before passing them","Strip @, whitespace, and query strings","Enforce the 1-15 char [A-Za-z0-9_] handle regex in your wrapper","Omit the username entirely to auto-detect the logged-in user"],"tags":["validation","argument","twitter"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}