{"record":{"id":"a68510cf5d546a3f","repo":"jackwener/OpenCLI","slug":"username-contains-unsupported-characters","errorCode":null,"errorMessage":"username contains unsupported characters","messagePattern":"username contains unsupported characters","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/tiktok/utils.js","lineNumber":50,"sourceCode":"    if (parsed > max) {\n        throw new ArgumentError(\n            `${name} must be <= ${max}`,\n            `Example: --${name} ${max}`,\n        );\n    }\n    return parsed;\n}\n\nexport function normalizeUsername(value) {\n    const username = String(value ?? '').trim().replace(/^@+/, '');\n    if (!username) {\n        throw new ArgumentError(\n            'username is required',\n            'Example: opencli tiktok following <username>',\n        );\n    }\n    if (!/^[A-Za-z0-9._-]+$/.test(username)) {\n        throw new ArgumentError(\n            'username contains unsupported characters',\n            'Pass the TikTok handle without @, for example: dictogo',\n        );\n    }\n    return username;\n}\n\nexport const NOTIFICATION_TYPES = {\n    all: { code: 0, label: 'all' },\n    likes: { code: 3, label: 'likes' },\n    comments: { code: 7, label: 'comments' },\n    mentions: { code: 6, label: 'mentions' },\n    followers: { code: 4, label: 'followers' },\n};\n\nexport function requireNotificationType(value) {\n    const key = String(value ?? 'all').trim().toLowerCase();\n    if (!Object.prototype.hasOwnProperty.call(NOTIFICATION_TYPES, key)) {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/utils.js#L32-L68","documentation":"After the emptiness check, normalizeUsername validates the handle against /^[A-Za-z0-9._-]+$/ and throws this ArgumentError when other characters are present. TikTok handles are restricted to letters, digits, dots, underscores and hyphens, so anything else (slashes, spaces, CJK characters, query strings) is treated as invalid input rather than being passed to the API.","triggerScenarios":"Passing a full profile URL like https://www.tiktok.com/@user?lang=en; passing a name with spaces or '@' in the middle ('@' is only stripped from the start); passing a display name containing emoji/CJK instead of the canonical handle; accidentally including quotes or shell artifacts.","commonSituations":"Pasting a URL instead of the handle; using the visible display name (which may contain spaces/emoji) rather than the @handle shown under the avatar; programmatically passing encoded values (%20, +).","solutions":["Pass only the bare handle: 'dictogo', not 'https://www.tiktok.com/@dictogo'.","If you have a URL, extract the path segment after '@' before calling (strip anything after '?').","Use the canonical @handle shown on the profile, not the display name.","Pre-validate with /^[A-Za-z0-9._-]+$/ after trimming and stripping leading '@'."],"exampleFix":"// before\nawait cli.tiktok.following('https://www.tiktok.com/@dictogo?lang=en'); // throws\n// after\nconst input = 'https://www.tiktok.com/@dictogo?lang=en';\nconst m = input.match(/@([A-Za-z0-9._-]+)/);\nawait cli.tiktok.following(m ? m[1] : input);","handlingStrategy":"validation","validationCode":"const HANDLE_RE = /^[A-Za-z0-9._-]+$/;\nfunction toHandle(input) {\n  const m = String(input ?? '').match(/@([A-Za-z0-9._-]+)/); // accepts profile URLs too\n  const handle = (m ? m[1] : String(input ?? '').trim().replace(/^@+/, ''));\n  if (!HANDLE_RE.test(handle)) throw new Error(`not a valid TikTok handle: ${input}`);\n  return handle;\n}","typeGuard":"const isValidHandle = (v) => typeof v === 'string' && /^[A-Za-z0-9._-]+$/.test(v.trim().replace(/^@+/, ''));","tryCatchPattern":"try {\n  await cli.tiktok.following(rawInput);\n} catch (e) {\n  if (/unsupported characters/.test(e.message)) {\n    console.error('Pass the bare handle (letters, digits, . _ -), not a URL or display name');\n  } else throw e;\n}","preventionTips":["Never pass profile URLs; extract the segment after '@' first","Use the canonical @handle, not the display name (which may contain spaces/emoji)","Strip query strings (?lang=...) before passing values","Pre-validate with /^[A-Za-z0-9._-]+$/ in scripts"],"tags":["validation","argument-error","cli","input-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}