feat: surface initError on the build when deploy fails#71
feat: surface initError on the build when deploy fails#71jonoirwinrsa wants to merge 1 commit intomainfrom
Conversation
When a deploy hits a terminal failure (e.g. capacity unavailable, init_failure), the backend now writes a user-facing message to the build's initError field synchronously. The CLI was polling the build status but discarding initError, so the user only saw "✗ Build failed with status: init_failure" with no actionable detail. This wires initError through buildStatusUpdateMsg → buildCompleteMsg → logDrainCompleteMsg and prints it after the failure line in both SimpleOutput and interactive modes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| type buildCompleteMsg struct { | ||
| status string | ||
| status string | ||
| initError *string |
There was a problem hiding this comment.
Rather just use string. The string being empty is sufficient to know that the error is not present, and I don't think we need to distinguish between the zero value and nil here?
The only check checks both:
if msg.initError != nil && *msg.initError != ""let's just simplify and do
if msg.initError != ""There was a problem hiding this comment.
So the reason it's tempting (I think) to put a pointer on the type is to be able to distinguish between 'present but empty' and 'not present'. I think that distinction is only useful if there's a functional difference between those two things.
In this case as far as I can tell there is no functional difference so let's just keep it to non-pointer. It makes the type a lot easier to work with
| Status string `json:"status"` | ||
| CreatedAt string `json:"createdAt"` | ||
| UpdatedAt string `json:"updatedAt"` | ||
| InitError *string `json:"initError,omitempty"` |
There was a problem hiding this comment.
As below
| InitError *string `json:"initError,omitempty"` | |
| InitError string `json:"initError,omitempty"` |
Summary
When a deploy fails terminally (e.g. capacity unavailable, init_failure), the backend writes a user-facing message to
build.initErrorsynchronously. The CLI was already polling build status but discardedinitError, so the user only saw✗ Build failed with status: init_failurewith no actionable detail.This adds
InitError *stringto theAppBuildAPI type, threads it throughbuildStatusUpdateMsg → buildCompleteMsg → logDrainCompleteMsg, and prints it after the failure line in both SimpleOutput and interactive modes.Related
Backend PR that populates the field: https://github.com/CerebriumAI/dashboard-backend/pull/3504
Test plan
go build ./...go test ./internal/ui/commands/...--simpleand interactive modes.initError, only the existing failure line should print.🤖 Generated with Claude Code