{"record":{"id":"aadbdf0bf0c16314","repo":"TryGhost/Ghost","slug":"your-username-is-not-a-valid-twitter-username","errorCode":null,"errorMessage":"Your Username is not a valid Twitter Username","messagePattern":"Your Username is not a valid Twitter Username","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/admin/src/settings/app/utils/social-urls/twitter.ts","lineNumber":13,"sourceCode":"import {createPlatformValidator} from './platform-validator';\n\n// X handles are ASCII-only by platform rule: 1–15 letters, numbers or underscores.\n// twitter.com URLs are accepted and canonicalised to x.com.\nconst twitter = createPlatformValidator({\n    domains: ['x.com', 'twitter.com'],\n    www: false,\n    pathTypes: [\n        {urlPrefix: '', storagePrefix: '@', rule: {extra: '_', min: 1, max: 15}}\n    ],\n    errors: {\n        invalidUrl: 'The URL must be in a format like https://x.com/yourUsername',\n        invalidUsername: 'Your Username is not a valid Twitter Username'\n    }\n});\n\nexport const validateTwitterUrl = twitter.validate;\nexport const twitterHandleToUrl = twitter.handleToUrl;\nexport const twitterUrlToHandle = twitter.urlToHandle;\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/apps/admin/src/settings/app/utils/social-urls/twitter.ts#L1-L20","documentation":"Thrown by the platform-validator engine for the Twitter/X definition when the username itself is invalid, OR when handleToUrl is called with an empty handle. Message declared in twitter.ts ('Your Username is not a valid Twitter Username'); thrown in platform-validator.ts at: query/fragment present in a non-fullPath username (line 247), the username rule check fails (line 255), or handleToUrl receives an empty handle (line 280). The X rule is ASCII alphanumerics plus underscore, length 1–15.","triggerScenarios":"Username fails the compiled rule: contains characters outside [a-zA-Z0-9_] (e.g. 'user.name', 'user-name'); length outside 1–15 (empty, or >15 chars like 'this_handle_is_too_long'); contains a '?' or '#' (query/fragment) in a URL username segment; OR handleToUrl('') with an empty stored handle.","commonSituations":"User typed a handle with a dot or hyphen (not allowed on X); handle longer than 15 characters; rendering a stored handle that's empty due to data corruption; user included a trailing query string in the URL.","solutions":["Use a handle of 1–15 ASCII letters, digits, or underscores only — no dots, hyphens, or spaces.","Guard handleToUrl against empty strings at the call site before invoking it.","Strip query strings and fragments from URLs before validation (they're not part of an X handle).","When rendering stored handles, wrap handleToUrl in try-catch and fall back to omitting the link."],"exampleFix":"// before — throws on empty/corrupt stored handle or out-of-rule handle\nconst url = twitterHandleToUrl(profile.x);\n\n// after — guard empty, try-catch the rest\nconst handle = profile.x?.trim();\nif (!handle) {\n    return null;\n}\ntry {\n    return twitterHandleToUrl(handle);\n} catch {\n    return null;\n}","handlingStrategy":"try-catch","validationCode":"// Validate the handle shape before calling handleToUrl\nfunction isValidTwitterHandleShape(h: string): boolean {\n    return /^[a-zA-Z0-9_]{1,15}$/.test(h);\n}","typeGuard":"null","tryCatchPattern":"const handle = profile.x?.trim();\nif (!handle) return null;\ntry {\n    return twitterHandleToUrl(handle);\n} catch {\n    return null;\n}","preventionTips":["Use 1–15 ASCII letters/digits/underscores only — no dots, hyphens, or spaces.","Guard handleToUrl against empty strings.","Strip query strings and fragments from URLs before validation.","Wrap handleToUrl in try-catch when rendering from stored data."],"tags":["twitter","x","social-urls","validation"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}