Programmatic navigation resolves to pages
Why it matters
Programmatic navigation to a non-existent route is worse UX than a static link to a non-existent route: the user clicks a button, takes a deliberate action, and ends up on a 404 with no breadcrumb back to where they were. router.push('/admin/users') when no app/admin/users/page.tsx exists is the exact shape of this failure. It breaks post-signup flows, post-payment redirects, and admin dashboards — all critical journeys the audit fixtures test.
Severity rationale
High because a bad router.push during a critical flow strands the user on a 404 mid-journey after they took an action.
Remediation
For each unresolved navigation call, either fix the specifier to point at a real route or create the destination file. In Next.js App Router using useRouter:
import { useRouter } from 'next/navigation'
const router = useRouter()
router.push('/admin/team') // matches app/admin/team/page.tsx
If the destination is genuinely missing, scaffold app/admin/users/page.tsx so the navigation has a target.
Detection
-
ID:
programmatic-navigation-resolves -
Severity:
high -
What to look for: Walk source files for calls to
router.push("..."),router.replace("..."),router.prefetch("..."),redirect("..."),permanentRedirect("..."),useNavigate()(...),navigate("..."),window.location.href = "...",window.location.assign("..."),window.location.replace("..."). Extract the first argument string literal. Apply the same normalization and resolution logic as the previous check. Count all programmatic navigation calls inspected, total resolved, total unresolved. -
Pass criteria: 100% of programmatic navigation literal arguments resolve to an existing page route. Report: "X programmatic navigation calls inspected, Y resolved, 0 unresolved."
-
Fail criteria: At least 1 programmatic navigation literal does not resolve.
-
Do NOT pass when: A
router.push()argument is constructed at runtime from a variable AND the base path of the constructed URL does not resolve — the same rule as the fetch-paths check. -
Skip (N/A) when: Project has 0 page route files.
-
Detail on fail:
"2 unresolved navigation calls: router.push('/admin/users') in src/components/AdminMenu.tsx (no app/admin/users/page.tsx exists), redirect('/login') in src/app/dashboard/page.tsx (no app/login/page.tsx)." -
Remediation: Programmatic navigation to non-existent routes results in a runtime 404 after a user action — usually worse UX than a static 404 because it surprises the user. Fix each one to point at an existing route, or create the missing route file:
// src/components/AdminMenu.tsx import { useRouter } from 'next/navigation' function AdminMenu() { const router = useRouter() // Bad: no app/admin/users/page.tsx exists // router.push('/admin/users') // Good: matches an existing route file router.push('/admin/team') }Alternatively, create the missing page file at
app/admin/users/page.tsxso the navigation has a target.
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ai-slop-hallucinations·automated