CLI and observability
Separate build and runtime logs
Diagnose compilation and installation failures from build output, and request-time failures from runtime logs tied to a deployment and route.
Vercel keeps two kinds of logs, and they answer two different questions. Build logs tell you what happened while Vercel installed dependencies and compiled the app. Runtime logs tell you what happened when the deployed code handled a request. Half of all debugging time gets wasted reading the wrong one.
Start from the phase that failed
Ask one question first: did the deployment reach Ready?
If it didn’t, the answer is in the build log. A missing package, a TypeScript error, a next build that ran out of memory. Open the deployment, read the log from the first red line, and fix the source.
If it did reach Ready and a page returns 500, the build has nothing to tell you. The failure happened at request time. Open the Logs tab for the project, filter by that deployment, and find the request. You can do the same from the terminal:
npx vercel@latest logs https://field-notes-3h7kq9p2d-flavio.vercel.app
You’ll see one line per invocation: the route, the status, the duration, and whatever your code printed. A database timeout, a missing environment variable, an unhandled exception in a server component: those all live here.
Rebuilding the same commit because a runtime request failed is the classic mistake. The build was fine. The rebuild will be fine too, and the page will still return 500.
Three streams, three questions
There’s a third source people forget. The team Activity log records who changed a setting, added a domain, or promoted a deployment. When something changed and nobody knows why, that’s where you look.
So: build logs explain one artifact, runtime logs explain traffic hitting it, activity explains configuration changes around it.
Make runtime logs worth reading
Your code decides what ends up in runtime logs. Log structured lines with the fields you’ll want to filter on:
console.log(JSON.stringify({
route: '/notes/[slug]',
status: 500,
durationMs: 812,
error: 'NoteNotFound'
}))
Route template, status, duration and a safe error class are enough. Never log full headers, cookies, request bodies, or process.env. Logs are visible to everyone on the team, and a token in a log is a leaked token.
Also, don’t treat the dashboard as an archive. Retention depends on your plan. If a log line matters for an incident report, ship it to a durable store with a Log Drain, or copy it out while it’s still there.
Try this on your own project: on a branch, break the build with a typo in an import, then fix it and add a route that throws only when ?fail=1 is present. Find each failure in the right log view and write the shortest factual diagnosis for both.
Lesson completed