wagoodman/dive · error
unable to set view to layer %q: %w
Error message
unable to set view to layer %q: %w
What it means
Raised when dive tries to make the 'layer' view the current (focused) view via gocui's Gui.SetCurrentView and gocui rejects it. It only executes when g.CurrentView() == nil, i.e. on the very first layout pass before any view has focus. SetCurrentView fails when the named view does not exist yet (not created by a prior SetView) or was deleted.
Source
Thrown at cmd/dive/cli/internal/ui/v1/layout/compound/layer_details_column.go:88
func (cl *LayerDetailsCompoundLayout) Layout(g *gocui.Gui, minX, minY, maxX, maxY int) error {
log.WithFields("ui", cl.Name()).Tracef("layout(minX: %d, minY: %d, maxX: %d, maxY: %d)", minX, minY, maxX, maxY)
layouts := []view.View{
cl.layer,
cl.layerDetails,
cl.imageDetails,
}
rowHeight := maxY / 3
for i := 0; i < 3; i++ {
if err := cl.layoutRow(g, minX, i*rowHeight, maxX, (i+1)*rowHeight, layouts[i].Name(), layouts[i].Setup); err != nil {
return fmt.Errorf("unable to layout %q: %w", layouts[i].Name(), err)
}
}
if g.CurrentView() == nil {
if _, err := g.SetCurrentView(cl.layer.Name()); err != nil {
return fmt.Errorf("unable to set view to layer %q: %w", cl.layer.Name(), err)
}
}
return nil
}
func (cl *LayerDetailsCompoundLayout) RequestedSize(available int) *int {
// "available" is the entire screen real estate, so we can guess when its a bit too small and take action.
// This isn't perfect, but it gets the job done for now without complicated layout constraint solvers
if available < 90 {
cl.layer.ConstrainLayout()
cl.constrainRealEstate = true
size := 8
return &size
}
cl.layer.ExpandLayout()
cl.constrainRealEstate = false
return nil
}View on GitHub (pinned to d6c691947f)
Solutions
- Look at the error just before this one in the log — a failed layoutRow for the layer view is the usual root cause; fix that first
- Verify no code path calls g.DeleteView on the layer view while the layout manager still runs
- On shutdown races, ensure gui.MainLoop has fully returned before tearing down view state
- Enlarge terminal / fix geometry so all three column views are created successfully
Example fix
// ensure the layer view exists before focusing it
if _, err := g.View(cl.layer.Name()); err == nil {
if _, err := g.SetCurrentView(cl.layer.Name()); err != nil {
return fmt.Errorf("unable to set view to layer %q: %w", cl.layer.Name(), err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the view exists before focusing it
if _, err := g.View(cl.layer.Name()); err != nil {
return nil // view not created yet; skip focus this pass
} Try / catch
if _, err := g.SetCurrentView(cl.layer.Name()); err != nil {
if errors.Is(err, gocui.ErrUnknownView) {
// benign on first pass; retry next layout
return nil
}
return fmt.Errorf("unable to set view to layer %q: %w", cl.layer.Name(), err)
} Prevention
- Create the layer view before any code path can call SetCurrentView
- Avoid deleting views while the layout manager is active
- Treat ErrUnknownView during startup as retryable on the next layout pass
When it happens
Trigger: Gui.SetCurrentView("layer") returning a non-nil error: the 'layer' view was never created because its layoutRow/SetView failed earlier in the same pass, the view was deleted by g.DeleteView elsewhere, or the view name registered by layoutRow does not match cl.layer.Name().
Common situations: A preceding layoutRow failure left the layer view missing; concurrent GUI teardown during Ctrl+C while a layout pass is in flight; custom builds that rename views or add views that steal/delete the layer view; race between gui.MainLoop shutdown and a queued layout.
Related errors
- unable to toggle filter view: %w
- unable to move the cursor, empty line
- failed to set UI: %w
- failed to set UI: %w
- unable to layout %q: %w
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/9d7d4a837ab32d99.
Report an issue: GitHub.