Diagnosing Server‑Side Pagination Failures in Vuetify 3 v‑data‑table
A step‑by‑step diagnostic guide for Vuetify 3 v‑data‑table server‑side pagination: recognize the stuck loader or empty rows, pinpoint the root cause with a quick‑reference table, run ordered checks, apply targeted fixes, and know when to escalate.
16 Jan 2026, 01:36 UTC

Problem: Table Stuck on Loader or Shows No Rows
You open a page that uses v-data-table with server-items-length and :server-items-length="total". The network tab reports a 200 OK response, yet the table either spins forever or renders an empty body. No JavaScript errors appear in the console.
Cause / Diagnostic Quick‑Reference
| Observed Symptom | Most Likely Cause | Fast Verification |
|---|---|---|
| Spinner never disappears | loading prop stays true after data arrives | Watch loading in Vue DevTools; it should flip to false once the promise resolves. |
| Empty rows, correct page count | Response missing totalCount or items array is empty for the requested slice | Inspect the JSON payload – it must contain totalCount and an items array of length ≤ items-per-page. |
| Wrong page requested | Pagination query parameters (page, itemsPerPage) not bound to the table’s @update:options event | Check the request URL – it should contain ?page=2&itemsPerPage=15 (or your chosen param names). |
| CORS error in console | Backend does not allow the origin | Open Network → Headers → Response; look for Access-Control-Allow-Origin. |
Ordered Diagnostic Checks
-
Inspect the outbound request. Open DevTools → Network, filter XHR/Fetch, click the pagination request. Verify:
- HTTP method (usually
GET). - Query string matches the table’s current page and page size.
- Request headers include
Accept: application/json.
- HTTP method (usually
-
Validate the server response shape. The JSON must be:
{ "totalCount": 342, "items": [ { "id": 1, "name": "Alpha" }, { "id": 2, "name": "Beta" } ] }totalCount(integer) – total rows across all pages.items(array) – exactly the slice for the requested page.
-
Confirm component prop bindings. In the
<v-data-table>template ensure:<v-data-table :items="rows" :items-per-page="pageSize" :server-items-length="total" :loading="isLoading" @update:options="fetchPage" > <!-- column slots --> </v-data-table>rowsreceives theitemsarray.totalreceivestotalCount.isLoadingis set totruebefore the request andfalseafter.fetchPagereadsoptions.pageandoptions.itemsPerPageto build the request.
-
Ensure
server-items-lengthis a number, not a string. Vue will coerce but a non‑numeric value can keep the pager disabled. -
Test the endpoint directly. Run in a terminal (requires network access, no special permissions):
Expected: HTTP 200, JSON withcurl -G "https://api.example.com/items" \ --data-urlencode "page=1" \ --data-urlencode "itemsPerPage=20" \ -H "Accept: application/json"totalCountanditems. Risks: if the API requires authentication, add-H "Authorization: Bearer <token>".
Fixes Mapped to Findings
| Finding | Fix | Code Change Example |
|---|---|---|
loading never resets |
Set isLoading = false in the finally block of the fetch function. |
|
Missing totalCount or empty items |
Update the backend to always return both fields, even for empty pages (return items: []). |
Backend pseudo‑code (Node/Express): |
| Wrong query parameter names | Align front‑end options mapping with back‑end expectations (e.g., page vs pageNumber). |
|
| CORS blocks the response | Add Access-Control-Allow-Origin: https://your‑app.com (or * for dev) on the API server. |
Express example: |
Escalation Criteria
- After applying the fixes above, the table still shows a spinner > 5 seconds on a fast network – involve the backend team to verify latency and payload size.
- Console shows
TypeError: Cannot read property 'length' of undefined– likely a version mismatch (Vuetify 2 syntax used in a v3 project). Upgrade the component usage to the v3 API. - Intermittent empty pages on high page numbers – check database offset/limit logic for off‑by‑one errors.
Limitations & Scope
- Applies to Vuetify 3.x (
v-data-tablewithserver-items-length). Vuetify 2 usespagination.syncand different prop names. - Assumes a REST‑like JSON endpoint; GraphQL or custom transport layers need analogous checks.
- Does not cover client‑side sorting/filtering combined with server pagination – those require additional
@update:optionshandling.
Verification Checklist
- Reload the page; the first page renders rows and the spinner disappears within 2 seconds.
- Open DevTools → Network; the pagination request returns
200withtotalCountand anitemsarray of the expected length. - In Vue DevTools, confirm
isLoadingtogglestrue → falseandrows/totalupdate. - Navigate to page 2, 3, and the last page; each loads without error.
When all checklist items pass, the server‑side pagination is functioning correctly. If any step fails, revisit the corresponding diagnostic row and apply the mapped fix.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.