# Registration & diagnostics

> Scope custom renderers and diagnose missing registrations.

Source: https://docs.inertiax.dev/table/guide/registration/

Use namespaced identifiers such as `acme/role` for custom column types, filter value types, and icon types. The server’s identifier must match the key registered in React.

Start with [Custom columns](https://docs.inertiax.dev/table/guide/custom-columns/) or [Custom filters](https://docs.inertiax.dev/table/guide/custom-filters/) for complete examples.

## Registration scope

Pass a `TableCustomizationOptions` object to `<TableProvider customization={...}>` for application-wide registration, or to `<AppTable customization={...} />` for one table. Resolution is built-in → provider → component.

**React**

```tsx
import { register, type TableCustomizationOptions } from '@inertiax/react-table';

const customization = {
  cellRenderers: [register('acme/role', RoleCell)],
} satisfies TableCustomizationOptions;
```

Here, `RoleCell` is the renderer from [Custom columns](https://docs.inertiax.dev/table/guide/custom-columns/). `register(key, value)` adds a new key; `replace(key, value)` overrides an existing one. Duplicate registrations and missing replacements fail with catalog and component context.

A column key selects data; its type selects the cell renderer. A clause input’s value type selects the filter input, while clause keys identify server comparisons. Registering a renderer does not add query behavior.

## Diagnose a missing renderer

The default `fallback: 'allow'` policy renders a fallback and records `INERTIAX_CATALOG_FALLBACK_USED` with the missing key. To make missing registrations fatal during development, configure the existing `TableProvider` in your shared layout:

**React**

```tsx
<TableProvider runtimeOptions={{ diagnostics: { fallback: 'error' } }}>
  {children}
</TableProvider>
```

Or observe diagnostics while keeping fallbacks:

**React**

```tsx
<TableProvider
  runtimeOptions={{
    diagnostics: {
      fallback: 'allow',
      onDiagnostic(diagnostic) {
        console.warn(diagnostic.code, diagnostic.key, diagnostic.componentId);
      },
    },
  }}
>
  {children}
</TableProvider>
```

These fragments replace the `TableProvider` configured during [installation](https://docs.inertiax.dev/table/installation/#add-the-providers). Invalid envelopes, callbacks, and registration operations fail independently of the fallback policy.

## Envelope pipelines

Use the `pipeline` option when a table must change a validated envelope before rendering, such as hiding the copy buttons in an embedded view that reuses a server table. For ordinary presentation changes, use [cells or regions](https://docs.inertiax.dev/table/guide/custom-renderers/).

**React**

```tsx
import { addStage, type TableProps } from '@inertiax/react-table';
import { isProblemEnvelope } from '@inertiax/table-protocol';

export const embedPipeline = [
  addStage('acme/no-copy', (envelope) => {
    if (isProblemEnvelope(envelope)) return envelope;
    const columns = envelope.component.columns.map((column) => ({ ...column, copyable: false }));
    return { ...envelope, component: { ...envelope.component, columns } };
  }),
] satisfies TableProps['pipeline'];
```

Pass it to the embedded table: `<AppTable prop="users" pipeline={embedPipeline} />`. Keep the array at module scope: a new array on each render recreates the table session, which loses selection and other client state. `TableProvider` takes the same `pipeline` option for every table under it.

Return problem envelopes unchanged: they have no columns. Add `@inertiax/table-protocol` to your dependencies to import `isProblemEnvelope()`. A stage failure or invalid output rejects the update and retains its cause. See [Envelope pipelines](https://docs.inertiax.dev/table/reference/react/#envelope-pipelines) for stage order and the other operations.
