{"record":{"id":"65800455a970b30b","repo":"aaif-goose/goose","slug":"editor-helper-not-set","errorCode":null,"errorMessage":"Editor helper not set","messagePattern":"Editor helper not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/session/input.rs","lineNumber":153,"sourceCode":"            if !editor_cmd.is_empty() {\n                let messages = extract_recent_messages(conversation_messages);\n                let message_refs: Vec<&str> = messages.iter().map(|s| s.as_str()).collect();\n                let (message, has_meaningful_content) =\n                    crate::session::editor::get_editor_input(&editor_cmd, &message_refs, None)?;\n\n                if has_meaningful_content {\n                    editor.add_history_entry(message.as_str())?;\n                    return Ok(InputResult::Message(message));\n                }\n                // Empty editor content — fall through to inline prompt\n            }\n        }\n    }\n\n    let completion_cache = editor\n        .helper()\n        .map(|h| h.completion_cache.clone())\n        .ok_or_else(|| anyhow::anyhow!(\"Editor helper not set\"))?;\n\n    let paste_state = Arc::new(std::sync::RwLock::new(PasteState::default()));\n\n    editor.bind_sequence(\n        rustyline::Event::Any,\n        rustyline::EventHandler::Conditional(Box::new(PasteCaptureHandler::new(\n            paste_state.clone(),\n        ))),\n    );\n\n    editor.bind_sequence(\n        rustyline::KeyEvent(rustyline::KeyCode::Enter, rustyline::Modifiers::NONE),\n        rustyline::EventHandler::Conditional(Box::new(PasteAwareEnterHandler::new(\n            paste_state.clone(),\n        ))),\n    );\n\n    editor.bind_sequence(","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/session/input.rs#L135-L171","documentation":"The rustyline Editor only yields a helper (and thus the tab-completion cache) when one was installed via set_helper(). input.rs reads editor.helper() to obtain the completion cache before the inline prompt loop; if no helper was installed it errors with 'Editor helper not set'. In shipped goose the helper is set unconditionally (session/mod.rs), so this is an internal invariant failure, not a user misconfiguration.","triggerScenarios":"Reaching the inline-prompt branch of input.rs with a rustyline Editor constructed without set_helper — only possible in custom builds or refactors that skip helper installation.","commonSituations":"Custom forks or in-progress PRs restructuring session input; essentially unseen in released binaries.","solutions":["Ensure set_helper is called before the interactive loop: editor.set_helper(Some(completer))","Update to a released goose version where the helper is installed unconditionally"],"exampleFix":"// before\nlet mut editor = Editor::<CustomHelper, DefaultHistory>::new()?;\n// helper never set\n// after\nlet mut editor = Editor::<CustomHelper, DefaultHistory>::new()?;\neditor.set_helper(Some(completer));","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn has_helper<H: Helper, I: History>(ed: &Editor<H, I>) -> bool {\n    ed.helper().is_some()\n}","tryCatchPattern":"let completion_cache = match editor.helper() {\n    Some(h) => h.completion_cache.clone(),\n    None => {\n        tracing::warn!(\"editor helper missing; continuing without completion cache\");\n        default_cache()\n    }\n};","preventionTips":["Always call editor.set_helper(...) immediately after constructing the Editor","In tests, assert the helper is set before entering the input loop"],"tags":["rustyline","cli","internal-invariant","completion"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}