Troubleshooting
Diagnose common failures from observable symptoms without bypassing safety checks.
Troubleshooting
Start from an observable symptom. Preserve the first failure and exact command before changing code, dependencies, environment, data, or provider state.
Safe evidence bundle
Record:
git status --short
git rev-parse HEAD
node --version
bun --version
pnpm --version
vp --version
docker compose ps
vp run --last-detailsInclude the failing command, exit code, expected behavior, smallest reproduction, relevant redacted logs, and whether the same failure occurs in an unmodified custom-scope reference scaffold.
Never include .env contents, auth links, cookies, API keys, OAuth secrets, webhook secrets,
database dumps, private customer data, signed upload URLs, or unreviewed agent transcripts. Name an
environment key; do not paste its value.
Install, checks, and builds
| Symptom | Observe first | Next action |
|---|---|---|
| Frozen install reports lock drift | pnpm --version, changed manifests, git diff -- pnpm-lock.yaml | restore pnpm 11.18.0 and the release lockfile; regenerate only for a deliberate package change |
| Supply-chain policy rejects install | exact rejected package/script and pnpm-workspace.yaml owner | review the package and install script; never blanket-enable all build scripts |
vp check fails only after scaffold | file, formatter diff, chosen scope/brand length | reproduce in a fresh custom scaffold and fix the source template |
| Vite+ command fails | owning package command and vp run --last-details | run pnpm verify:toolchain; do not rewrite the app |
| Type checking fails | first diagnostic and package-native tsc -b --noEmit | restore release pins, fix the type boundary, and retain type-aware checks |
| Bun server build/test fails | pinned Bun version, direct test/build output | restore Bun 1.3.14 before diagnosing an upgrade; Node is not a server-runtime fallback |
| Web build warns about chunk size | emitted entry and PWA precache sizes | treat as visible performance risk; a successful build does not make the warning disappear |
Local server and database
| Symptom | Exact observation | Follow-up |
|---|---|---|
| Postgres is unavailable | docker compose ps and redacted host/port/database name | compare DATABASE_URL ownership with Compose; do not paste credentials |
/health is 200 but /ready is 503 | migration output, Postgres health, readiness log | inspect initialization and failed migration diagnosis |
| Server exits before binding | first startup error; rendered template/migration directories | restore required resources or explicit paths; do not bypass preload |
| Migration fails | dbmate status, exact migration, disposable reproduction | never edit a released migration or forge schema_migrations |
| DB tests skip unexpectedly | RUN_DB_INTEGRATION_TESTS and resolved test database name, without credentials | use a disposable migrated Postgres and the documented opt-in |
Use Setup, Testing, and the migration golden paths for exact commands.
Authentication and browser sessions
| Symptom | Inspect |
|---|---|
| Local email or magic link missing | structured server log; local delivery deliberately does not call Resend |
| Auth request returns 401 | browser API origin, cookie presence/attributes, credentials: include, CORS, trusted origins |
| Verification/reset link is wrong | FRONTEND_URL, SERVER_URL, callback allowlist, provider redirect URL |
| Google button is absent | complete Google configuration; the flow is deliberately hidden when unset |
| OAuth works locally but not live | exact HTTPS origin/callback configured in app, Better Auth, provider, and deployment |
| Another user's resource is visible | stop deployment; add owner-scoped SQL and missing/cross-owner tests |
Follow Authentication and Security. Never diagnose sessions by logging raw cookies, tokens, passwords, auth links, or provider secrets.
Billing, email, and storage
| Symptom | Inspect |
|---|---|
| Checkout/portal is unavailable | selected provider, complete environment, plan mapping, authenticated user |
| Paid state differs from provider | event ID/type/timestamp, local claim/state, provider subscription, ordering—not secret/payload dumps |
| Webhook retries or returns non-2xx | failed webhook diagnosis; repair then provider replay |
| Billing state committed but email absent | post-commit notification log; do not replay the financial event solely to resend communication |
| Resend rejects sender | verified domain, EMAIL_FROM, environment/account ownership, provider error code |
| Upload endpoint is unavailable | selected provider, shared bucket values, provider fields, and private staging lifecycle policy |
| Presigned PUT fails in browser | staging CORS, exact method/origin, URL expiry, signed byte length and Content-Type |
| Upload confirmation fails | claim owner/state/expiry, staged size/MIME/signature bytes, and copy precondition |
Follow Billing, Email, and Storage. A provider dashboard is evidence of provider state, not permission to mutate local database rows by hand.
Deployment and PWA
| Symptom | Inspect |
|---|---|
| Railway/Dokploy image is not healthy | build architecture, migration/template copy, environment validation, /ready logs |
| Vercel loads 404 on a client route | SPA rewrite and output directory |
| Live auth loops or loses session | exact HTTPS origins, cookie attributes, proxy headers, API URL, CORS |
| Old UI persists after deployment | deployed artifact ID, service-worker update, browser/PWA cache, release commit |
| Sentry source maps or tunnel fail | build-time token/org/project, runtime DSN, server project allowlist, exact Sentry host |
| Rollback restores code but not behavior | database/provider changes that outlived the deployment |
Use Deployment. Clear only disposable local browser/PWA state during diagnosis; do not instruct customers to erase application data as a generic fix.
Branding, customization, and removal
- A stale name usually means a surface is missing from the counted manifest or generated email was not refreshed. Follow Customization.
- An
@appreference in a generated buyer is a scaffold contract failure, not a request for global replacement. - A removed integration that still asks for a key, mounts a route, ships a dependency, or appears in current claims was disabled, not removed. Follow Removing subsystems.
- Historical decision records may retain a retired name with explicit historical context.
Escalation
Use Requesting support only after producing a safe reproduction. A failure caused by product changes may still be diagnosable, but it is not automatically a foundation defect. An unmodified reference failure on the current tagged release is the strongest support signal.