Skip to content

feat: surface initError on the build when deploy fails#71

Open
jonoirwinrsa wants to merge 1 commit intomainfrom
feat/show-init-error
Open

feat: surface initError on the build when deploy fails#71
jonoirwinrsa wants to merge 1 commit intomainfrom
feat/show-init-error

Conversation

@jonoirwinrsa
Copy link
Copy Markdown
Contributor

Summary

When a deploy fails terminally (e.g. capacity unavailable, init_failure), the backend writes a user-facing message to build.initError synchronously. The CLI was already polling build status but discarded initError, so the user only saw ✗ Build failed with status: init_failure with no actionable detail.

This adds InitError *string to the AppBuild API type, threads it through buildStatusUpdateMsg → 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/...
  • Trigger a capacity failure on dev — verify the CLI prints the capacity message after the failure line in both --simple and interactive modes.
  • Trigger a non-capacity init_failure (e.g. crashing app) — verify nothing regresses; if backend doesn't populate initError, only the existing failure line should print.

🤖 Generated with Claude Code

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>
@jonoirwinrsa jonoirwinrsa requested a review from wesrobin May 7, 2026 19:19
type buildCompleteMsg struct {
status string
status string
initError *string
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 != ""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread internal/api/types.go
Status string `json:"status"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
InitError *string `json:"initError,omitempty"`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As below

Suggested change
InitError *string `json:"initError,omitempty"`
InitError string `json:"initError,omitempty"`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants