{"record":{"id":"24174e0252cc6964","repo":"GraphiteEditor/Graphite","slug":"footprint-widget-should-return-multiple-rows","errorCode":null,"errorMessage":"Footprint widget should return multiple rows","messagePattern":"Footprint widget should return multiple rows","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"editor/src/messages/portfolio/document/node_graph/node_properties.rs","lineNumber":638,"sourceCode":"\t\t\t\t.label(\"Resolution\")\n\t\t\t\t.mode_range()\n\t\t\t\t.min(0.)\n\t\t\t\t.range_min(Some(1.))\n\t\t\t\t.range_max(Some(100.))\n\t\t\t\t.unit(\"%\")\n\t\t\t\t.on_update(parameter_widgets_info.update_value(move |x: &NumberInput| {\n\t\t\t\t\tlet resolution = (bounds * x.value.unwrap_or(100.) / 100.).as_uvec2().max((1, 1).into()).min((4000, 4000).into());\n\n\t\t\t\t\tlet footprint = Footprint { resolution, ..footprint };\n\t\t\t\t\tTaggedValue::Footprint(footprint)\n\t\t\t\t}))\n\t\t\t\t.on_commit(commit_value)\n\t\t\t\t.widget_instance(),\n\t\t);\n\t}\n\n\tlet widgets = [LayoutGroup::row(location_widgets), LayoutGroup::row(scale_widgets), LayoutGroup::row(resolution_widgets)];\n\tlet (last, rest) = widgets.split_last().expect(\"Footprint widget should return multiple rows\");\n\t*extra_widgets = rest.to_vec();\n\tlast.clone()\n}\n\npub fn transform_widget(parameter_widgets_info: ParameterWidgetsInfo, extra_widgets: &mut Vec<LayoutGroup>) -> LayoutGroup {\n\tlet ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info;\n\n\tlet mut location_widgets = start_widgets(&parameter_widgets_info);\n\tlocation_widgets.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());\n\n\tlet mut rotation_widgets = vec![TextLabel::new(\"\").widget_instance()];\n\tadd_blank_assist(&mut rotation_widgets);\n\trotation_widgets.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());\n\n\tlet mut scale_widgets = vec![TextLabel::new(\"\").widget_instance()];\n\tadd_blank_assist(&mut scale_widgets);\n\tscale_widgets.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());\n","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/editor/src/messages/portfolio/document/node_graph/node_properties.rs#L620-L656","documentation":"widgets is a fixed-length [LayoutGroup; 3] array (location, scale, resolution rows). split_last() on an array of statically known non-zero length always returns Some, so this .expect can never fire at runtime — it is a compile-time-known invariant expressed as an assertion. Its real job is to peel the resolution row off as the returned widget and store the location/scale rows in extra_widgets.","triggerScenarios":"Not reachable at runtime with the current three-element array literal. It could only panic if widgets were refactored into an empty array or a dynamically-built Vec whose length is not guaranteed.","commonSituations":"Developers finding this string in crash reports and hunting a bug that cannot exist; later refactors converting the array to a runtime Vec, which would newly make None possible.","solutions":["Classify it as unreachable; no runtime fix is required.","Replace with array destructuring (let [a, b, last] = widgets;) so emptiness becomes a compile-time error instead of a hidden runtime assumption.","If the collection ever becomes dynamically sized, handle None explicitly rather than expecting."],"exampleFix":"// before\nlet (last, rest) = widgets.split_last().expect(\"Footprint widget should return multiple rows\");\n*extra_widgets = rest.to_vec();\nlast.clone()\n\n// after — length is statically known, no runtime panic possible\nlet [location, scale, resolution] = widgets;\n*extra_widgets = vec![location, scale];\nresolution","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Destructure fixed-length arrays instead of split_last().expect so the compiler proves length","Reserve .expect for conditions the type system cannot prove, never statically-known lengths","When triaging crash strings, first classify reachability — a fixed 3-element array cannot yield None"],"tags":["rust","graphite","unreachable-invariant","ui-widgets"],"backgroundTag":"invariant-assertion-failed","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}