{"record":{"id":"98a312cfc1064d41","repo":"wagoodman/dive","slug":"unable-to-setup-row-layout-for-s-w","errorCode":null,"errorMessage":"unable to setup row layout for %s: %w","messagePattern":"unable to setup row layout for (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/dive/cli/internal/ui/v1/layout/compound/layer_details_column.go","lineNumber":64,"sourceCode":"\treturn nil\n}\n\nfunc (cl *LayerDetailsCompoundLayout) layoutRow(g *gocui.Gui, minX, minY, maxX, maxY int, viewName string, setup func(*gocui.View, *gocui.View) error) error {\n\tlog.WithFields(\"ui\", cl.Name()).Tracef(\"layoutRow(g, minX: %d, minY: %d, maxX: %d, maxY: %d, viewName: %s, <setup func>)\", minX, minY, maxX, maxY, viewName)\n\t// header + border\n\theaderHeight := 2\n\n\t// TODO: investigate overlap\n\t// note: maxY needs to account for the (invisible) border, thus a +1\n\theaderView, headerErr := g.SetView(viewName+\"Header\", minX, minY, maxX, minY+headerHeight+1, 0)\n\n\t// we are going to overlap the view over the (invisible) border (so minY will be one less than expected)\n\tbodyView, bodyErr := g.SetView(viewName, minX, minY+headerHeight, maxX, maxY, 0)\n\n\tif utils.IsNewView(bodyErr, headerErr) {\n\t\terr := setup(bodyView, headerView)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to setup row layout for %s: %w\", viewName, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (cl *LayerDetailsCompoundLayout) Layout(g *gocui.Gui, minX, minY, maxX, maxY int) error {\n\tlog.WithFields(\"ui\", cl.Name()).Tracef(\"layout(minX: %d, minY: %d, maxX: %d, maxY: %d)\", minX, minY, maxX, maxY)\n\n\tlayouts := []view.View{\n\t\tcl.layer,\n\t\tcl.layerDetails,\n\t\tcl.imageDetails,\n\t}\n\n\trowHeight := maxY / 3\n\tfor i := 0; i < 3; i++ {\n\t\tif err := cl.layoutRow(g, minX, i*rowHeight, maxX, (i+1)*rowHeight, layouts[i].Name(), layouts[i].Setup); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to layout %q: %w\", layouts[i].Name(), err)","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/cmd/dive/cli/internal/ui/v1/layout/compound/layer_details_column.go#L46-L82","documentation":"TUI layout error from layoutRow(): after gocui.SetView created (or returned) the header and body views for a row, the caller-supplied setup() callback failed and is wrapped with the view name. Setup configures the freshly created view pair (e.g. wrapping, titles, render helpers), so this fires only when the views are newly created (IsNewView) — typically on first layout or after a view teardown.","triggerScenarios":"Initial TUI layout (or re-layout after resize destroyed views) where the per-view setup function returns an error: setting view options on a view with invalid geometry, or a renderer failing to bind to the new view object.","commonSituations":"Terminals too small for the header+body rows; resizing forcing view recreation mid-session; bugs in view setup code paths exercised by unusual geometries.","solutions":["Check the wrapped inner error from the setup callback for the concrete cause.","Run in a terminal of at least ~80x24 so each row has room for the 2-line header plus body.","Avoid resizing while the TUI is starting up.","Report upstream with terminal size and the full error chain if reproducible at normal sizes."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure at least ~80x24 terminal dimensions so header+body rows fit.","Avoid resizing during TUI startup when views are first created.","Report persistent setup failures with terminal size and inner error."],"tags":["dive","tui","gocui","layout","internal"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}