TanStack/table · error

[@tanstack-table/angular] The provided symbol is not a compo

Error message

[@tanstack-table/angular] The provided symbol is not a component

What it means

resolveComponentTypeMetadata uses Angular's reflectComponentType to read @Component metadata from a Type passed to FlexRenderComponent. If the value is a class but has no component metadata (not decorated with @Component, or metadata not preserved by the build), the mirror is null and this error is thrown.

Source

Thrown at packages/angular-table/src/flex-render/flexRenderComponent.ts:332

  }
}

interface ResolvedComponentMetadata<TComponent = unknown> {
  readonly mirror: ComponentMirror<TComponent>
  readonly inputNames: ReadonlyMap<string, string>
  readonly outputNames: ReadonlySet<string>
}

const typeCache = new WeakMap<Type<unknown>, ResolvedComponentMetadata>()

function resolveComponentTypeMetadata<T>(
  type: Type<T>,
): ResolvedComponentMetadata<T> {
  let metadata = typeCache.get(type) as ResolvedComponentMetadata<T> | undefined
  if (metadata) return metadata
  const mirror = reflectComponentType(type)
  if (!mirror) {
    throw new Error(
      `[@tanstack-table/angular] The provided symbol is not a component`,
    )
  }
  const inputNames = new Map<string, string>()
  const outputNames = new Set<string>()
  for (const input of mirror.inputs) {
    inputNames.set(input.propName, input.templateName)
    if (input.templateName !== input.propName) {
      inputNames.set(input.templateName, input.templateName)
    }
  }
  for (const output of mirror.outputs) {
    // Outputs are read from the component instance, so only their class
    // property names are valid here. Template aliases are not instance keys.
    outputNames.add(output.propName)
  }
  metadata = { mirror, inputNames, outputNames }
  typeCache.set(type, metadata)

View on GitHub (pinned to d01c01bedb)

Solutions

  1. Ensure the value passed to FlexRenderComponent is a class decorated with @Component({...})
  2. Check that decorators are not stripped at build time (correct tsconfig target/useDefineForClassFields and Angular compiler settings; don't run esbuild/swc without the Angular plugin)
  3. Verify imports resolve to the decorated component class, not a re-exported or duplicate undecorated copy

Example fix

// before
class UserCell { } // no decorator
flexRenderComponent(UserCell); // throws
// after
@Component({ selector: 'user-cell', template: '{{ value() }}' })
class UserCell { }
flexRenderComponent(UserCell); // works
Defensive patterns

Strategy: validation

Validate before calling

import { reflectComponentType } from '@angular/core';
if (!reflectComponentType(maybeComponent)) {
  throw new Error('Expected an @Component-decorated class for FlexRender');
}

Type guard

function isComponent<T>(t: Type<T> | unknown): t is Type<T> {
  return typeof t === 'function' && !!reflectComponentType(t as Type<T>);
}

Try / catch

try {
  const comp = flexRenderComponent(type);
} catch (e) {
  if (e.message.includes('not a component')) {
    console.error('Pass an @Component-decorated class to FlexRenderComponent:', type?.name);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Passing a non-component class (plain class, directive, or a class whose @Component decorator was stripped by a build misconfiguration) as the component argument to FlexRenderComponent, so reflectComponentType(type) returns null.

Common situations: Using FlexRender with a header/cell component defined without @Component; JIT/AOT misconfiguration where decorators are removed (e.g. missing angularCompilerOptions, running TS without emitDecoratorMetadata path expected by Angular); passing an injected abstract class.

Related errors


AI-assisted analysis of TanStack/table@d01c01bedb (2026-08-28). Data as JSON: /api/errors/f6649670577d0af8. Report an issue: GitHub.