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

  1. 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
  2. Verify no code path calls g.DeleteView on the layer view while the layout manager still runs
  3. On shutdown races, ensure gui.MainLoop has fully returned before tearing down view state
  4. 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

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


AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15). Data as JSON: /api/errors/9d7d4a837ab32d99. Report an issue: GitHub.