{"record":{"id":"58f153184dce46c0","repo":"aaif-goose/goose","slug":"failed-to-set-global-subscriber","errorCode":null,"errorMessage":"Failed to set global subscriber: {}","messagePattern":"Failed to set global subscriber: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/logging.rs","lineNumber":26,"sourceCode":"/// Sets up the logging infrastructure for the CLI.\n/// Logs go to a JSON file only (no console output).\npub fn setup_logging(name: Option<&str>) -> &'static Result<()> {\n    INIT.get_or_init(|| {\n        use tracing_subscriber::util::SubscriberInitExt;\n\n        init_goose_request_log()?;\n        let config = goose::logging::LoggingConfig {\n            component: \"cli\",\n            name,\n            extra_directives: &[\"goose_cli=info\"],\n            console: false,\n            json: true,\n        };\n        let subscriber = goose::logging::build_logging_subscriber(&config)?;\n\n        subscriber\n            .try_init()\n            .map_err(|e| anyhow::anyhow!(\"Failed to set global subscriber: {}\", e))?;\n        Ok(())\n    })\n}\n\n#[cfg(test)]\nmod tests {\n    use goose::tracing::langfuse_layer;\n    use std::env;\n    use tempfile::TempDir;\n\n    fn setup_temp_home() -> TempDir {\n        let temp_dir = TempDir::new().unwrap();\n        if cfg!(windows) {\n            env::set_var(\"USERPROFILE\", temp_dir.path());\n        } else {\n            env::set_var(\"HOME\", temp_dir.path());\n        }\n        temp_dir","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/logging.rs#L8-L44","documentation":"goose-cli sets up its file-only JSON tracing subscriber with SubscriberInitExt::try_init inside a OnceLock (crates/goose-cli/src/logging.rs:24-26). try_init returns Err when some other component has already installed a global default tracing subscriber in this process, because Rust allows only one global default subscriber. The OnceLock only guards goose's own repeat calls, not a subscriber installed by another crate or an earlier init in the same process.","triggerScenarios":"Calling setup_logging after another crate (a test harness, an embedded tracing setup, or a library calling tracing::subscriber::set_global_default / try_init first) already set the global default; also any second, differently-configured init path that bypasses the OnceLock.","commonSituations":"Running goose-cli code inside test binaries that install their own subscriber (e.g. tracing-subscriber's env-filter init in tests), embedding goose-cli functions in another binary that logs first, or a dependency (telemetry/otel) that initializes tracing during its own setup.","solutions":["Find which component installed a global subscriber first (search the process init path for set_global_default/try_init) and let goose's setup_logging run before it, or remove the duplicate init","If double-init is expected and harmless, treat the 'already initialized' failure as Ok instead of an error","In tests, use per-test capturing subscribers (e.g. tracing_test or a subscriber-scoped guard) instead of the global default"],"exampleFix":"// before\nsubscriber\n    .try_init()\n    .map_err(|e| anyhow::anyhow!(\"Failed to set global subscriber: {}\", e))?;\n\n// after (tolerate an already-installed global subscriber)\nuse tracing_subscriber::util::SubscriberInitExt;\nlet _ = subscriber.try_init(); // logs nothing when the global default is already set","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust: tolerate a subscriber that was already installed globally\nuse tracing_subscriber::util::SubscriberInitExt;\n\nmatch subscriber.try_init() {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"already set\") => {\n        // Another component owns the global default; keep logging via its subscriber\n        tracing::debug!(\"global tracing subscriber already set: {e}\");\n    }\n    Err(e) => return Err(anyhow::anyhow!(\"Failed to set global subscriber: {e}\")),\n}","preventionTips":["Initialize tracing exactly once per process, before any dependency that may install its own subscriber","In test suites, prefer per-test capturing subscribers over global defaults","Grep dependency init paths for set_global_default/try_init when embedding goose-cli code"],"tags":["rust","tracing","logging","initialization"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}