{"record":{"id":"43d4cd2c103c7cc4","repo":"FyroxEngine/Fyrox","slug":"malformed-bus-graph","errorCode":null,"errorMessage":"Malformed bus graph!","messagePattern":"Malformed bus graph!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fyrox-sound/src/bus.rs","lineNumber":398,"sourceCode":"                Some(bus.input_buffer())\n            } else {\n                None\n            }\n        })\n    }\n\n    /// Removes an audio bus at the given handle.\n    pub fn remove_bus(&mut self, handle: Handle<AudioBus>) -> AudioBus {\n        assert_ne!(handle, self.root);\n\n        let bus = self.buses.free(handle);\n        let parent_bus = &mut self.buses[bus.parent_bus];\n\n        let position = parent_bus\n            .child_buses\n            .iter()\n            .position(|h| *h == handle)\n            .expect(\"Malformed bus graph!\");\n        parent_bus.child_buses.remove(position);\n\n        bus\n    }\n\n    /// Returns a handle of the primary audio bus. Primary bus outputs its samples directly to an audio playback\n    /// device.\n    pub fn primary_bus_handle(&self) -> Handle<AudioBus> {\n        self.root\n    }\n\n    /// Returns a reference to the primary audio bus.\n    pub fn primary_bus_ref(&self) -> &AudioBus {\n        &self.buses[self.root]\n    }\n\n    /// Returns a reference to the primary audio bus.\n    pub fn primary_bus_mut(&mut self) -> &mut AudioBus {","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/FyroxEngine/Fyrox/blob/76c91aad8eca488ce527b1af707be8b3b24ad72d/fyrox-sound/src/bus.rs#L380-L416","documentation":"remove_bus detaches a bus from the sound bus graph by removing its handle from its parent's child_buses list. The expect fires when the child handle cannot be found in the parent's list, meaning the bus graph is inconsistent (corrupted invariant). This indicates an internal bug or misuse that broke parent/child bookkeeping.","triggerScenarios":"Calling remove_bus on a bus whose parent_bus index is stale or whose handle was never (or no longer) registered as a child of its declared parent — e.g. after manually mutating bus.parent_bus without updating the old parent's child list, or double-removing a bus.","commonSituations":"Manually rewiring buses by writing parent_bus directly; removing a bus twice; restoring buses from a snapshot inconsistently; engine version changes altering bus graph layout.","solutions":["Only remove buses through remove_bus and never mutate parent_bus/child_buses fields directly.","Check that the bus handle is valid and still connected before removal (verify via buses.borrow(bus).parent_bus chain).","Guard against double removal — ensure remove_bus is called once per bus handle."],"exampleFix":"// before\nbus_graph.buses.borrow_mut(bus).parent_bus = other; // corrupts graph\nbus_graph.remove_bus(bus); // panics\n// after\nbus_graph.remove_bus(bus);\nbus_graph.add_bus(other, bus); // use API to rewire","handlingStrategy":"validation","validationCode":"let parent = bus_graph.buses.borrow(bus).parent_bus;\nassert!(bus_graph.buses.borrow(parent).child_buses.iter().any(|h| *h == bus));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mutate bus graph fields directly; use add_bus/remove_bus APIs","Avoid removing the same bus twice"],"tags":["audio","graph-invariant","panic","fyrox-sound"],"backgroundTag":"internal-invariant-violation","analyzedSha":"76c91aad8eca488ce527b1af707be8b3b24ad72d","analyzedAt":"2026-09-10T16:04:01.633Z","contentChangedAt":"2026-09-10T16:04:01.633Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}