{"record":{"id":"f50779001edcca97","repo":"TryGhost/Ghost","slug":"your-username-is-not-a-valid-youtube-username","errorCode":null,"errorMessage":"Your Username is not a valid YouTube Username","messagePattern":"Your Username is not a valid YouTube Username","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/admin/src/settings/app/utils/social-urls/youtube.ts","lineNumber":17,"sourceCode":"import {createPlatformValidator} from './platform-validator';\n\n// YouTube profile URLs come in three shapes: modern @handles (3–30 chars,\n// letters/numbers/._- with no boundary punctuation — non-Latin scripts are\n// supported), legacy /user/ usernames and /channel/ IDs (UC + 22 chars).\n// Bare input defaults to an @handle.\nconst youtube = createPlatformValidator({\n    domains: ['youtube.com'],\n    www: true,\n    pathTypes: [\n        {urlPrefix: '@', storagePrefix: '@', rule: {unicode: true, extra: '._-', min: 3, max: 30, notAtBoundary: '._-', notConsecutive: '.'}},\n        {urlPrefix: 'user/', storagePrefix: 'user/', rule: {extra: '._-', min: 1, max: 50}},\n        {urlPrefix: 'channel/', storagePrefix: 'channel/', rule: {patterns: [/^UC[a-zA-Z0-9_-]{22}$/]}}\n    ],\n    errors: {\n        invalidUrl: 'The URL must be in a format like https://www.youtube.com/@yourUsername, https://www.youtube.com/user/yourUsername, or https://www.youtube.com/channel/yourChannelId',\n        invalidUsername: 'Your Username is not a valid YouTube Username'\n    }\n});\n\nexport const validateYouTubeUrl = youtube.validate;\nexport const youtubeHandleToUrl = youtube.handleToUrl;\nexport const youtubeUrlToHandle = youtube.urlToHandle;\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/apps/admin/src/settings/app/utils/social-urls/youtube.ts#L1-L24","documentation":"Thrown by the platform-validator engine for the YouTube definition when the username for the matched path type is invalid, or handleToUrl is called empty. Message declared in youtube.ts ('Your Username is not a valid YouTube Username'); thrown in platform-validator.ts at: query/fragment in username (line 247), username rule check failure (line 255), or empty handle in handleToUrl (line 280). The rule depends on the path type: @handle (Unicode, 3–30 chars, ._-, no boundary ._-, no consecutive dots), user/ (._-, 1–50), channel/ (must match /^UC[a-zA-Z0-9_-]{22}$/).","triggerScenarios":"For @handles: length outside 3–30, disallowed characters, leading/trailing ._- (notAtBoundary), or consecutive dots. For user/: length outside 1–50 or charset. For channel/: the ID doesn't match UC + 22 alphanumerics/_-. Also: a URL username segment contains '?' or '#' (query/fragment); OR handleToUrl('') with an empty stored handle.","commonSituations":"User typed an @handle under 3 or over 30 characters; channel ID malformed (not UC-prefixed or wrong length); rendering an empty stored handle; user appended a query string; user mixed conventions ('user/@name' leaves a leftover @ that the rule rejects).","solutions":["Match the rule for the chosen path type: @handle (3–30, Unicode, no boundary ._-, no consecutive dots), user/ (1–50, ._-.), or channel/ (UC + 22 chars).","Guard handleToUrl against empty strings before calling.","Strip query strings and fragments from URLs before validation.","Avoid mixing conventions (e.g. user/@name) — a leftover @ after a structural prefix is intentionally not stripped."],"exampleFix":"// before — throws on empty/corrupt stored handle or out-of-rule handle\nconst url = youtubeHandleToUrl(profile.youtube);\n\n// after — guard empty, try-catch the rest\nconst handle = profile.youtube?.trim();\nif (!handle) {\n    return null;\n}\ntry {\n    return youtubeHandleToUrl(handle);\n} catch {\n    return null;\n}","handlingStrategy":"try-catch","validationCode":"// Validate the handle shape for the matched YouTube path type\nfunction isValidYouTubeHandleShape(h: string): boolean {\n    if (!h) return false;\n    if (h.startsWith('@')) {\n        const name = h.slice(1);\n        return [...name].length >= 3 && [...name].length <= 30;\n    }\n    if (h.startsWith('channel/')) {\n        return /^UC[a-zA-Z0-9_-]{22}$/.test(h.slice('channel/'.length));\n    }\n    if (h.startsWith('user/')) {\n        const name = h.slice('user/'.length);\n        return name.length >= 1 && name.length <= 50;\n    }\n    return false;\n}","typeGuard":"null","tryCatchPattern":"const handle = profile.youtube?.trim();\nif (!handle) return null;\ntry {\n    return youtubeHandleToUrl(handle);\n} catch {\n    return null;\n}","preventionTips":["Match the rule for the chosen path type: @handle (3–30, Unicode, no boundary ._-, no consecutive dots), user/ (1–50), channel/ (UC + 22 chars).","Guard handleToUrl against empty strings.","Strip query strings and fragments from URLs before validation.","Don't mix conventions (user/@name)."],"tags":["youtube","social-urls","validation"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}