{"record":{"id":"0fdaa64e19047b56","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"error-handling-irq","errorCode":null,"errorMessage":"Error handling IRQ","messagePattern":"Error handling IRQ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"20_timer_callbacks/kernel/src/bsp/device_driver/arm/gicv2.rs","lineNumber":212,"sourceCode":"        &'irq_context self,\n        ic: &exception::asynchronous::IRQContext<'irq_context>,\n    ) {\n        // Extract the highest priority pending IRQ number from the Interrupt Acknowledge Register\n        // (IAR).\n        let irq_number = self.gicc.pending_irq_number(ic);\n\n        // Guard against spurious interrupts.\n        if irq_number > GICv2::MAX_IRQ_NUMBER {\n            return;\n        }\n\n        // Call the IRQ handler. Panic if there is none.\n        self.handler_table.read(|table| {\n            match table[irq_number] {\n                None => panic!(\"No handler registered for IRQ {}\", irq_number),\n                Some(descriptor) => {\n                    // Call the IRQ handler. Panics on failure.\n                    descriptor.handler().handle().expect(\"Error handling IRQ\");\n                }\n            }\n        });\n\n        // Signal completion of handling.\n        self.gicc.mark_comleted(irq_number as u32, ic);\n    }\n\n    fn print_handler(&self) {\n        use crate::info;\n\n        info!(\"      Peripheral handler:\");\n\n        self.handler_table.read(|table| {\n            for (i, opt) in table.iter().skip(32).enumerate() {\n                if let Some(handler) = opt {\n                    info!(\"            {: >3}. {}\", i + 32, handler.name());\n                }","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/bsp/device_driver/arm/gicv2.rs#L194-L230","documentation":"After finding a registered IRQ descriptor, the GICv2 driver calls descriptor.handler().handle() and expects Ok(()); if the handler itself reports failure, the .expect(\"Error handling IRQ\") panics. This library throws it because an IRQ handler that cannot service its interrupt leaves the peripheral in a stuck state and the error must be surfaced loudly.","triggerScenarios":"A registered IRQ handler's handle() implementation returns Err — e.g. the timer handler cannot clear its match/status register, a device's status register read fails the handler's internal validity checks, or the handler's expected state does not match reality when the IRQ fires.","commonSituations":"Timer handler called but timer registers were reconfigured concurrently, handler written for a different device revision whose status bits differ, IRQ shared/raced so the handler finds nothing to service and errors out, or a handler whose internal invariants were violated by earlier init mistakes.","solutions":["Inspect the failing handler's handle() implementation and its error type to see which internal condition failed.","Fix the handler so it correctly acknowledges/clears the interrupt source in the peripheral's status registers.","Verify device initialization order — the handler's device must be fully initialized before its IRQ is enabled.","If handle() returns Err for spurious interrupts, make the handler tolerate them (return Ok for no-op firings) instead of erroring."],"exampleFix":"// before\nfn handle(&self) -> Result<(), &'static str> {\n    Err(\"unexpected interrupt\") // propagates -> expect(\"Error handling IRQ\") panic\n}\n// after\nfn handle(&self) -> Result<(), &'static str> {\n    self.clear_status();\n    Ok(())\n}","handlingStrategy":"validation","validationCode":"// Handlers must be able to service their IRQ; verify the source is pending before enabling:\nassert!(timer.status_pending_bit_is_accessible(), \"timer IRQ source must be serviceable\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make handle() infallible where possible: acknowledge/clear unconditionally and reserve Err for truly impossible states.","Fully initialize the device before enabling its IRQ.","Handle spurious IRQs gracefully (ack and return Ok) instead of returning Err.","Unit-test handlers against the datasheet's status-register semantics."],"tags":["interrupts","gicv2","aarch64","bare-metal","panic"],"backgroundTag":"irq-handler-failed","analyzedSha":"644474cc09f755249f9c55d99a5d1e07a2562fc7","analyzedAt":"2026-09-06T09:25:56.584Z","contentChangedAt":"2026-09-06T09:25:56.584Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}