A client that fetches /api/user/profile when the server only defines /api/users/me returns 404 on every call in production — and AI tools are specifically prone to inventing plausible-sounding endpoints that do not exist. The user sees a loading spinner that never resolves, or a silent data-load failure that reads as a blank page. This is reference-integrity at the API boundary and it aligns directly with OWASP A05 (Security Misconfiguration) when the 404 exposes stack traces.
Critical because a broken fetch URL produces a user-visible 404 on every call and silently corrupts every page that depends on the data.
For each unresolved URL, either create the missing route handler or correct the client specifier. In Next.js App Router, the handler lives next to the URL path in app/api/...:
// app/api/user/profile/route.ts
export async function GET() {
return Response.json({ /* ... */ })
}
If you route through next.config.* rewrites, verify the rewrite source matches the fetch specifier exactly.
ID: ai-slop-hallucinations.route-references.client-fetch-paths-resolve
Severity: critical
What to look for: Walk source files for calls to fetch(...), axios.get/post/put/patch/delete/request(...), ky.get/post/put/patch/delete(...), useSWR("..."), useQuery({ queryFn: ... fetch("...") }), mutate("..."). Extract the first argument string literal. SKIP any URL with a scheme (http://, https://, ws://, wss://) — these are external API calls. SKIP mailto:, tel:, data: URIs. For the remaining relative URLs starting with /, normalize dynamic segments by converting Next.js [param] ↔ Express :param ↔ template literal ${var} ↔ OpenAPI {param} to a canonical placeholder (e.g., :PARAM). Match against the project's API route tree from the API_ROUTES map built in the analysis step. Count all relative fetch URLs inspected, total resolved, total unresolved. Sample at most 100 unique URLs and report the sample size.
Pass criteria: 100% of relative fetch URLs resolve to an existing server route file. Report: "X unique relative fetch URLs inspected, Y resolved, 0 unresolved."
Fail criteria: At least 1 relative fetch URL does not resolve to a server route file after dynamic-segment normalization.
Do NOT pass when: A fetch URL is constructed at runtime from a variable (fetch(/api/users/${id})) but the base path /api/users/[id] route does not exist — runtime construction does not exempt the base path from resolution.
Skip (N/A) when: Project has no API routes detected (no app/api/, no pages/api/, no routes/, no server/) AND no next.config.* rewrites referencing /api/* paths.
Cross-reference: For broader API contract analysis, the API Design audit (api-design) covers endpoint design quality.
Detail on fail: "4 unresolved fetch URLs: '/api/user/profile' in src/components/UserCard.tsx (no matching route file under app/api/user/), '/api/posts/[id]/comments' in src/hooks/useComments.ts (route file missing). Sampled 47 of 47 unique fetch URLs."
Remediation: A fetch to a non-existent route returns 404 in production — and AI tools love to hallucinate plausible-looking API endpoints. Fix each unresolved URL:
// Either create the missing route file
// app/api/user/profile/route.ts
export async function GET() {
return Response.json({ /* ... */ })
}
// Or fix the fetch call to point at an existing route
fetch('/api/users/me') // existing route
If you use a Next.js rewrites config or an API gateway, the check normalizes through next.config.* rewrites — make sure rewrites are declared.