{"record":{"id":"1b414851aff5157d","repo":"withastro/astro","slug":"invalid-transition-name-transitionname","errorCode":null,"errorMessage":"Invalid transition name {${transitionName}}","messagePattern":"Invalid transition name (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/runtime/server/transition.ts","lineNumber":95,"sourceCode":"\t\t\t\tcodepoint < 0x80\n\t\t\t\t\t? codepoint === 95\n\t\t\t\t\t\t? '__'\n\t\t\t\t\t\t: (reEncodeValidChars[codepoint] ?? '_' + codepoint.toString(16).padStart(2, '0'))\n\t\t\t\t\t: String.fromCodePoint(codepoint);\n\t\t}\n\t}\n\t// Digits and minus sign at the beginning of the string are special, so we simply prepend an underscore\n\treturn reEncodeInValidStart[result.codePointAt(0) ?? 0] ? '_' + result : result;\n}\n\nexport function renderTransition(\n\tresult: SSRResult,\n\thash: string,\n\tanimationName: TransitionAnimationValue | undefined,\n\ttransitionName: string,\n) {\n\tif (typeof (transitionName ?? '') !== 'string') {\n\t\tthrow new Error(`Invalid transition name {${transitionName}}`);\n\t}\n\t// Default to `fade` (similar to `initial`, but snappier)\n\tif (!animationName) animationName = 'fade';\n\tconst scope = createTransitionScope(result, hash);\n\tconst name = transitionName ? cssesc(reEncode(transitionName), { isIdentifier: true }) : scope;\n\tconst sheet = new ViewTransitionStyleSheet(scope, name);\n\n\tconst animations = getAnimations(animationName);\n\tif (animations) {\n\t\taddPairs(animations, sheet);\n\t} else if (animationName === 'none') {\n\t\tsheet.addFallback('old', 'animation: none; mix-blend-mode: normal;');\n\t\tsheet.addModern('old', 'animation: none; opacity: 0; mix-blend-mode: normal;');\n\t\tsheet.addAnimationRaw('new', 'animation: none; mix-blend-mode: normal;');\n\t\tsheet.addModern('group', 'animation: none');\n\t}\n\n\tconst css = escapeStyleText(sheet.toString());","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/runtime/server/transition.ts#L77-L113","documentation":"`renderTransition` handles `transition:name` rendering for View Transitions. The transition name must be a string (a CSS identifier is derived from it via `cssesc`). If `transitionName` (null-coalesced to `''`) is not of type `string` — e.g. a number, boolean, object, or array — Astro cannot build a valid CSS custom-identifier and throws.","triggerScenarios":"Passing `transition:name={123}` (number), a boolean, an object/array, or `undefined` that survives the `?? ''` coercion to a non-string type; an expression returning a non-string used as the transition name.","commonSituations":"Dynamic transition names computed from numeric IDs without string conversion; binding `transition:name` to a data field that is occasionally a number; spread-props carrying a non-string value.","solutions":["Ensure the `transition:name` value is always a string: `transition:name={String(id)}`.","Coerce numeric/computed values before binding them.","Validate dynamic values when iterating lists that produce transition names."],"exampleFix":"// before\n<div transition:name={item.id} />   // item.id is a number -> throws\n\n// after\n<div transition:name={String(item.id)} />","handlingStrategy":"type-guard","validationCode":"function assertTransitionName(name: unknown): asserts name is string {\n  if (typeof (name ?? '') !== 'string') {\n    throw new Error(`Invalid transition name {${String(name)}}`);\n  }\n}","typeGuard":"const isTransitionName = (v: unknown): v is string =>\n  typeof (v ?? '') === 'string';\n\n// In template:\ntransition:name={isTransitionName(name) ? name : String(name ?? '')}","tryCatchPattern":null,"preventionTips":["Always coerce transition names to strings, especially numeric IDs.","Type `transition:name` props as `string`.","Validate dynamic transition names when rendering lists."],"tags":["view-transitions","transition","css","type-validation"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}