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
- Ensure the value passed to FlexRenderComponent is a class decorated with @Component({...})
- 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)
- 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
- Always decorate classes passed to FlexRenderComponent with @Component
- Verify build tooling preserves Angular decorators (Angular compiler plugin in esbuild/vite/webpack)
- Check reflectComponentType() in dev assertions before passing dynamic types
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.