Troubleshooting
Common mistakes, error messages, and how to fix them
Use this page when a table does not load, returns 404/422, or behaves differently than expected. Work through the checklist top to bottom.
Quick diagnostic checklist
Is the table registered?
php artisan tinker
>>> config('api-tables-config.tables.users')Should return model, tableClass, and optional middlewares. If null, add the entry and clear config cache:
php artisan config:clearDoes TABLENAME match the config key?
// config key: 'users'
const TABLENAME = 'users'; // must match exactlyA mismatch causes "Required {table} Table Not Exists".
Is the user authenticated?
Default middleware is auth:sanctum. Unauthenticated requests fail before your table code runs. Test with a valid Bearer token.
Is the URL correct for your guard?
With guards => ['api'] and Laravel's default api prefix:
GET /api/api-table/control-tables/load-table/usersNot /api-table/... unless web is in your guards list.
Does load-table return columns?
curl -s -H "Authorization: Bearer $TOKEN" \
https://your-app.test/api/api-table/control-tables/load-table/users | jq .If success: true but columns: [], check $TBLColumns on your table class.
Error messages
| Message / symptom | Likely cause | Fix |
|---|---|---|
Required {table} Table Not Exists | Table not in config or wrong tableName in URL | Register in api-tables-config.tables |
Action is not defined | Action key in URL does not match setRowActions() / setBulkActions() keys | Keys are slugified (Export Excel → export_excel) |
| 401 Unauthorized | Missing or expired token | Re-authenticate; check Sanctum setup |
| 403 / middleware abort | Per-table middleware rejected request | Check middlewares on table config |
Empty items but data exists in DB | Filters too restrictive, or setInitialBuilder() scopes query | Log the builder SQL; test without filters |
| Column shows blank | Wrong data_src, missing relation eager load, or callback error | Verify attribute name; use with() in builder |
| Export fails over 3000 rows | Instant export limit | Use email report bulk action instead |
| Email report never arrives | Queue not running | Start php artisan queue:work; check user_model |
| Translation shows raw key | Missing lang entry | Add api-table.{tableName}.{label} in lang files |
Constructor and instantiation
APITablesService::getTableInstance() calls:
new $tableConfig['tableClass']($user, $params);TableAbstract::__construct() currently accepts only string $tableName. Your generated stub should look like:
public function __construct(...$args)
{
parent::__construct(self::TABLENAME);
}Or match whatever signature your team's base wrapper uses. If you see “Too few arguments” or “Too many arguments” on instantiation, align the child constructor with how the service passes $user and $params.
Senior note
If you need $params inside the table (e.g. scoping by warehouseId), read them from request()->input('params') in setInitialBuilder() until constructor signatures are unified across the package and app tables.
Filters not working
| Check | Detail |
|---|---|
filter_name matches payload field | Client sends { "field": "name", ... } — field must equal your filter's filter_name |
| Operator allowed | TextFilter allows = and like only unless you override operators in props |
| Column exists on builder | Filter applies to query builder — relation filters may need joins in setInitialBuilder() |
Test query in isolation:
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"filters":[{"field":"name","operator":"like","value":"john"}],"page":1,"perPage":10}' \
https://your-app.test/api/api-table/control-tables/query-table/usersActions not appearing in UI
- Action must be returned from
setRowActions()/setBulkActions()(merged with defaults) isApplicableCallbackreturning false hides the action for that rowshowInWeb: falsehides from web clients- Frontend must load structure after your deploy — hard refresh or clear cache
Performance (senior)
| Symptom | Investigation |
|---|---|
Slow query-table | N+1 queries — add with() for relations used in columns |
| Timeout on export | Reduce filter scope; use email report for large datasets |
| High memory on large pages | Lower perPage default on frontend; index filtered/sorted columns |
Use Laravel Debugbar or DB::listen() locally to inspect queries from setInitialBuilder().
Still stuck?
- Compare your
load-tableJSON with Table structure - Compare with a working table in the same app (copy config + class pattern)
- Check Laravel log:
storage/logs/laravel.log - Ask frontend team if they see structure loaded in Redux/network tab