{"record":{"id":"894ac927ed6f9da8","repo":"RightNow-AI/openfang","slug":"draw-failed","errorCode":null,"errorMessage":"draw failed","messagePattern":"draw failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openfang-cli/src/tui/screens/init_wizard.rs","lineNumber":684,"sourceCode":"\n    let original_hook = std::panic::take_hook();\n    std::panic::set_hook(Box::new(move |info| {\n        ratatui::restore();\n        original_hook(info);\n    }));\n\n    let mut terminal = ratatui::init();\n    let mut state = State::new();\n\n    let (test_tx, test_rx) = std::sync::mpsc::channel::<bool>();\n    let (migrate_tx, migrate_rx) =\n        std::sync::mpsc::channel::<Result<openfang_migrate::report::MigrationReport, String>>();\n    let (copilot_tx, copilot_rx) = std::sync::mpsc::channel::<Result<CopilotAuthEvent, String>>();\n\n    let result = loop {\n        terminal\n            .draw(|f| draw(f, f.area(), &mut state))\n            .expect(\"draw failed\");\n\n        // Check for Copilot auth events\n        if state.step == Step::CopilotAuth {\n            while let Ok(event) = copilot_rx.try_recv() {\n                match event {\n                    Ok(CopilotAuthEvent::DeviceCode {\n                        user_code,\n                        verification_uri,\n                    }) => {\n                        state.copilot_user_code = user_code;\n                        state.copilot_verification_uri = verification_uri;\n                        state.copilot_auth_status = CopilotAuthStatus::WaitingForUser;\n                    }\n                    Ok(CopilotAuthEvent::Authenticated) => {\n                        state.copilot_auth_status = CopilotAuthStatus::FetchingModels;\n                    }\n                    Ok(CopilotAuthEvent::Models(models)) => {\n                        state.copilot_auth_status = CopilotAuthStatus::Done;","sourceCodeStart":666,"sourceCodeEnd":702,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-cli/src/tui/screens/init_wizard.rs#L666-L702","documentation":"The init-wizard screen renders itself each loop iteration with `terminal.draw(...).expect(\"draw failed\")`. Ratatui's `draw` returns `io::Result`; any failure writing the frame or querying terminal capabilities panics here. This wizard runs while background migration/copilot auth threads send events over channels, but the panic comes purely from terminal I/O, not from those channels.","triggerScenarios":"Rendering the wizard when stdout is not a TTY (redirected output), the terminal resizes to invalid/zero dimensions, the terminal is detached mid-wizard, or any underlying write/flush on the terminal backend fails.","commonSituations":"Piping the init wizard's output to a file, running it from scripts or CI, terminal emulators reporting zero-size after resize, or SSH sessions that drop during the (long-running) wizard.","solutions":["Launch the wizard in a real interactive terminal without output redirection.","Add a TTY guard before starting the wizard and print instructions instead of entering TUI mode.","Handle draw errors with `?` and exit the wizard loop gracefully rather than panicking.","Handle resize events and clamp/validate terminal size before drawing."],"exampleFix":"// before\nterminal\n    .draw(|f| draw(f, f.area(), &mut state))\n    .expect(\"draw failed\");\n\n// after\nterminal\n    .draw(|f| draw(f, f.area(), &mut state))\n    .with_context(|| format!(\"wizard draw failed (terminal size {:?})\", terminal.size().ok()))?;","handlingStrategy":"fallback","validationCode":"if !atty::is(atty::Stream::Stdout) {\n    eprintln!(\"init wizard needs an interactive terminal\");\n    std::process::exit(1);\n}\nlet (cols, rows) = terminal.size()? .into(); // reject zero-size\nif cols == 0 || rows == 0 { eprintln!(\"terminal size invalid\"); std::process::exit(1); }","typeGuard":null,"tryCatchPattern":"// propagate instead of expect\nterminal.draw(|f| draw(f, f.area(), &mut state))\n    .context(\"wizard draw failed\")?;","preventionTips":["Validate TTY and terminal dimensions before starting the wizard","Gracefully exit the wizard loop on draw errors (restore terminal state in a guard)","Avoid long blocking waits that outlive the terminal session without disconnect detection","Test the wizard under piped output and CI to catch non-tty regressions"],"tags":["tui","io","ratatui","terminal"],"backgroundTag":"stdout-not-a-tty","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}