{"record":{"id":"db2835068f95e711","repo":"angular/angular","slug":"650","errorCode":"650","errorMessage":"'${instruction}' value must be a string of CSS classes or an animation function, got ${stringify(value)}","messagePattern":"'(.+?)' value must be a string of CSS classes or an animation function, got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/animation/utils.ts","lineNumber":48,"sourceCode":"  (typeof ngServerMode === 'undefined' || !ngServerMode) &&\n  typeof document !== 'undefined' &&\n  // tslint:disable-next-line:no-toplevel-property-access\n  typeof document?.documentElement?.getAnimations === 'function';\n\n/**\n * Helper function to check if animations are disabled via injection token\n */\nexport function areAnimationsDisabled(lView: LView): boolean {\n  const injector = lView[INJECTOR]!;\n  return injector.get(ANIMATIONS_DISABLED, DEFAULT_ANIMATIONS_DISABLED);\n}\n\n/**\n * Asserts a value passed in is actually an animation type and not something else\n */\nexport function assertAnimationTypes(value: string | Function, instruction: string) {\n  if (value == null || (typeof value !== 'string' && typeof value !== 'function')) {\n    throw new RuntimeError(\n      RuntimeErrorCode.ANIMATE_INVALID_VALUE,\n      `'${instruction}' value must be a string of CSS classes or an animation function, got ${stringify(value)}`,\n    );\n  }\n}\n\n/**\n * Asserts a given native element is an actual Element node and not something like a comment node.\n */\nexport function assertElementNodes(nativeElement: Element, instruction: string) {\n  if ((nativeElement as Node).nodeType !== Node.ELEMENT_NODE) {\n    throw new RuntimeError(\n      RuntimeErrorCode.ANIMATE_INVALID_VALUE,\n      `'${instruction}' can only be used on an element node, got ${stringify((nativeElement as Node).nodeType)}`,\n    );\n  }\n}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/core/src/animation/utils.ts#L30-L66","documentation":"assertAnimationTypes guards the value given to the class-based animation instructions animate.enter/animate.leave: it must be a string of CSS classes or a function (the AnimationClassBindingFn receiving the class list and element). A null/undefined or non-string/non-function value throws RuntimeError 650 because the animation runner can neither parse classes nor call it.","triggerScenarios":"Calling animate.enter(...) or animate.leave(...) (in host bindings, directive code, or templates) with a value that is not a string or function: animate.enter(null), a number, or a component field that is undefined because it was never initialized or arrived async.","commonSituations":"Config values fetched from a server and not yet loaded when the binding evaluates; typed config objects where a typo yields undefined; passing an object literal of options instead of a class string; SSR-safe code that nulls out bindings.","solutions":["Ensure the value is a CSS class string, e.g. 'fade-in scale', or a function like (classes, element) => 'anim-' + classes.join(' ').","Initialize the component field used by the binding to a valid string instead of leaving it undefined.","Guard async config: fall back to a default class string until loaded.","If you meant to disable the animation conditionally, use the ANIMATIONS_DISABLED injection token rather than nulling the value."],"exampleFix":"// before\nanimate.enter(undefined);\nhost: { 'class.enter': 'this.config.classes' }  // config not loaded yet\n\n// after\nanimate.enter('fade-in');\nhost: { 'class.enter': 'this.config?.classes ?? \"fade-in\"' }","handlingStrategy":"type-guard","validationCode":"// Before binding or passing a value to animate.enter/animate.leave:\nfunction safeAnimClasses(v: unknown, fallback = ''): string {\n  return typeof v === 'string' ? v : fallback;\n}\n// template: [class.enter]=\"safeAnimClasses(cfg?.classes, 'fade-in')\"","typeGuard":"export function isAnimationClassValue(\n  v: unknown,\n): v is string | ((classes: string[], element: Element) => string) {\n  return typeof v === 'string' || typeof v === 'function';\n}","tryCatchPattern":null,"preventionTips":["Type config fields consumed by animations as string | ((classes, el) => string) and initialize them.","Default async-loaded animation config to a known class string until resolved.","Never pass option objects or numbers where a class string/function is expected."],"tags":["animations","runtime-error","type-error","animate-enter"],"backgroundTag":"invalid-animation-value-type","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}