# Troubleshooting

> Resolve common installation, rendering, data, and request failures.

Source: https://docs.inertiax.dev/table/troubleshooting/

Find your symptom below. If an error includes a code or diagnostic path, use the [error reference](https://docs.inertiax.dev/table/errors/) for its exact meaning.

## Private packages cannot be installed

Composer and your JavaScript package manager install InertiaX only after you [connect the InertiaX registry](https://docs.inertiax.dev/table/installation/#connect-the-inertiax-registry) with the **Connect the registry** commands on your portal’s **Registry keys** page.

| Symptom                                                                                                                                                         | Check                                                                                                                 |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `Could not find a matching version of package inertiax/laravel-table`                                                                                           | Composer isn’t connected to the InertiaX registry: run the portal’s Composer commands in your application’s directory |
| `404 Not Found - GET https://registry.npmjs.org/@inertiax%2freact-table` (other package managers print a similar 404 or `Not found` for an `@inertiax` package) | Your package manager looks for `@inertiax` packages on the public npm registry: run the portal’s commands for it      |
| `401 Unauthorized`                                                                                                                                              | The key is active in the portal and hasn’t been rotated or revoked since you ran its commands                         |
| `403 Forbidden`                                                                                                                                                 | Your InertiaX access is active and the key isn’t revoked                                                              |
| Package not found                                                                                                                                               | Package name, registry endpoint, and authentication; private registries may conceal unauthorized packages             |
| Works locally, fails in CI                                                                                                                                      | Install job can access the protected secret and creates authentication before installation                            |

See [Early access](https://docs.inertiax.dev/early-access/) for keeping keys safe locally and in CI, and [Request help](https://docs.inertiax.dev/table/errors/#request-help) for what to send if the portal’s commands still fail.

## The table is unstyled

Import the stylesheet in your browser entry point:

**React**

```ts
import '@inertiax/react-table/styles.css';
```

If it is already imported, check that the built CSS loads in the browser. `base.css` supplies only the functional foundation; your application must add its own visual styling. See [Styling](https://docs.inertiax.dev/table/guide/styling/#choose-the-stylesheet).

## The table is empty or shows the wrong records

An empty table with headers is a valid rendered result. Run the source query in the same request context, then check the table’s search, filters, page, and page size. Also check that React reads the intended prop.

For unexpected records, correct the [server query scope](https://docs.inertiax.dev/table/guide/security/#authorize-and-scope-the-query). For stale page links after records disappear, use the table’s [reset action](https://docs.inertiax.dev/table/guide/url-recovery/) to return to page 1.

## The Inertia prop is missing or invalid

Use the same name in PHP and React:

**Laravel**

```php
UsersTable::make('users')
```

**React**

```tsx
<AppTable prop="users" />
```

`INERTIAX_INERTIA_PROP_MISSING` means the named page prop is absent. `INERTIAX_TABLE_QUERY_PROP_INVALID` means it is not a complete valid table response. Inspect the page props and return the table builder as shown in [Your first table](https://docs.inertiax.dev/table/quick-start/).

A component mismatch means a response for one table reached another table’s session. Use [distinct names](https://docs.inertiax.dev/table/guide/multiple-tables/) for multiple instances.

## The provider is missing

Check that the page uses the shared persistent layout containing `InertiaProvider` and `TableProvider`, as shown in [Installation](https://docs.inertiax.dev/table/installation/#add-the-providers). Table hooks must also run inside a table renderer. See [Direct envelope](https://docs.inertiax.dev/table/guide/direct-rendering/#ownership-and-disposal) for the lower-level renderer owners.

## Search, sorting, or filtering is missing

Enable the capability on the column:

**Laravel**

```php
TextColumn::make('name')->searchable()->sortable()->filterable();
```

Also check table-level `sorting(false)` or `autoFilters(false)` settings. For Eloquent and collections, searchable non-text columns need a [custom search strategy](https://docs.inertiax.dev/table/guide/query-callbacks/#search-a-stored-field). Custom sources require searchable columns to keep `type('text')` and handle search in the source; see [Custom-source search](https://docs.inertiax.dev/table/reference/source/#search).

## An Inertia generation fails

Use matching 2.x or matching 3.x Laravel and React adapters. Check the actual resolutions in both lockfiles, then rebuild the frontend after changing versions. See [Compatibility](https://docs.inertiax.dev/table/compatibility/).

## Back returns to the same page after opening a table link

This is an edge case in native Inertia URL handling that can also occur without InertiaX. Investigate it only if the first Back navigation unexpectedly leaves you on the same page.

Compare the URL you opened with the initial Inertia page URL. The query values may match while their order or encoding differs:

```text
Opened:   /invoices?invoices_search=alice&invoices_page=2
Response: /invoices?invoices_page=2&invoices_search=alice
```

Laravel’s default Inertia page URL uses a query string normalized by Symfony. Inertia compares that URL with the browser URL as strings; a mismatch can add a history entry during initialization. Capture the original path and query **before Inertia initializes**, then compare it with the initial page URL from `usePage().url`. By component mount, the address bar may already have changed.

If you confirm this mismatch, optionally add this line **inside** your existing `app/Http/Middleware/HandleInertiaRequests.php` class:

**Laravel**

```php
use \InertiaX\Http\Middleware\Concerns\PreservesInertiaUrl;
```

The helper uses Inertia’s supported [page URL resolver](https://inertiajs.com/docs/v3/the-basics/routing#customizing-the-page-url) to retain raw query order/encoding and Laravel’s base path, including a correctly configured trusted proxy prefix. It affects every Inertia page URL. If you already define `urlResolver()`, review and merge the behavior yourself; a class method takes precedence over the trait. Do not decode the query string. URL fragments stay in the browser and are not sent to PHP.

### Upstream discussion

The [URL encoding discussion in inertia-laravel #663](https://github.com/inertiajs/inertia-laravel/pull/663) and [URL readability issue #707](https://github.com/inertiajs/inertia-laravel/issues/707) are closed. In #707, a maintainer recommends customizing the resolver; [merged PR #739](https://github.com/inertiajs/inertia-laravel/pull/739) introduced that API. These links cover related URL normalization and customization, not a dedicated report or confirmed fix for the exact initial Back-button symptom above.

Tested versions

The extra entry reproduced without InertiaX in Chromium with Inertia Core 2.3.18, 3.6.1, and 3.8.0. The resolver was verified with Inertia Laravel 2.0.25 and 3.3.1; Chromium checks preserved Back/Forward navigation and a URL fragment. Other browsers and deployments need their own verification.

## A reload or request fails

For `INERTIAX_INERTIA_RELOAD_FAILED` or `INERTIAX_TABLE_INTEGRATION_DISPATCH_FAILED`, inspect the original cause, browser response, Laravel logs, requested prop name, and protocol diagnostic. Retry is available for a failed request; invalid definitions or payloads need correction first.

A newer interaction or unmount can cancel an older request. If an older result replaces newer state, check that one integration owns the table session and the Inertia generations match. See [Request lifecycle](https://docs.inertiax.dev/table/guide/request-lifecycle/).

## A custom renderer uses fallback

Match the Laravel `type('acme/role')` of a column, or `valueType('acme/role')` of a filter clause, to the React registration’s `key: 'acme/role'` and check the registration scope. `INERTIAX_CATALOG_FALLBACK_USED` identifies the missing type. See [Registration & diagnostics](https://docs.inertiax.dev/table/guide/registration/#diagnose-a-missing-renderer) to make it fatal in development.

## A collection callback fails

An Eloquent-only callback cannot run against a collection. Implement collection behavior and declare `DataSourceKind::Collection`, or keep an Eloquent source. See [Custom query behavior](https://docs.inertiax.dev/table/guide/query-callbacks/).

## Row identity or selection fails

Declare the row key as a column, including for empty results. Every row must have a unique key. For custom keys on possibly empty model collections, set `rowKey()` explicitly. See [Row identity](https://docs.inertiax.dev/table/reference/table/#row-identity).

Selection contains only IDs in the current result page. Page changes can therefore clear it; see [Selection](https://docs.inertiax.dev/table/guide/selection/).

## An inferred column has the wrong type

Use an explicit column such as `NumberColumn::make('score')`. Model casts take precedence over schema inference, and unsupported casts fall back to text. A `tinyint(1)` column becomes a boolean column, so a value other than 0 and 1 fails with `Boolean column [level] cannot cast int to boolean`. Declare such a column explicitly, for example as `NumberColumn::make('level')`. See [Automatic columns](https://docs.inertiax.dev/table/reference/column/#automatic-columns).

## The envelope is rejected

`INERTIAX_PROTOCOL_VERSION_UNSUPPORTED` indicates an unsupported protocol major. `INERTIAX_PROTOCOL_DECODE_FAILED` indicates invalid data or table semantics. Inspect the first reported path against the [protocol reference](https://docs.inertiax.dev/table/protocol/).

Align incompatible packages, or correct the producer or custom pipeline. Do not edit `protocolVersion` to bypass validation.

## Request help

Email <contact@inertiax.dev> with the [diagnostic details](https://docs.inertiax.dev/table/errors/#request-help).

## PHP autocomplete

InertiaX ships PHP types and PHPDoc for builder completion. No IDE-helper generation is required. In VS Code, use a PHP language server such as Intelephense; the official Laravel extension adds Laravel-specific assistance. PhpStorm also reads the bundled `ide.json` for built-in identifier suggestions. Custom namespaced types remain valid.

`UsersTable::make('users')` returns a Table builder, so methods such as `data()` are available. Custom builder classes should declare their generic relationship as shown in [Table inheritance](https://docs.inertiax.dev/table/guide/table-inheritance/#custom-builders).

Field names inside `TextColumn::make('…')` are not automatically tied to a model. A reusable table can receive different queries or collections through `data()`. The Laravel VS Code extension does not currently read InertiaX’s PhpStorm metadata.

## A callback cannot resolve a scalar parameter

Use the callback’s context name, rather than the domain field name:

**Laravel**

```php
// For a column named total_cents:
->transformUsing(fn (float $value): float => $value / 100)
```

`fn (int $cents)` fails because `cents` is not supplied. The exception lists available names; see [Callback context](https://docs.inertiax.dev/table/reference/callbacks/). A named value with an incompatible type also fails. For example, `NumberColumn` casts to float by default; use `float $value` or choose `numberCast('int')` before requiring `int $value`.
