{"record":{"id":"ef985b85b9489b96","repo":"dbt-labs/dbt-core","slug":"attrs-updater-should-only-be-called-once","errorCode":null,"errorMessage":"attrs_updater should only be called once","messagePattern":"attrs_updater should only be called once","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-tracing/src/span_info.rs","lineNumber":431,"sourceCode":"{\n    let mut attrs_updater = Some(attrs_updater);\n    with_current_span(move |span_ref| {\n        // Find the closest span with the expected TelemetryAttributes type.\n        // Scope iterator starts from the current span and goes up to the root.\n        for span_ref in span_ref.scope() {\n            let mut span_ext_mut = span_ref.extensions_mut();\n\n            if let Some(attrs) = span_ext_mut\n                // Get the current attributes\n                .get_mut::<TelemetryAttributes>()\n                .expect(\"Telemetry hasn't been properly initialized. Missing span event attributes\")\n                // Try downcasting to the expected type\n                .downcast_mut::<A>()\n            {\n                // Found the expected attributes, call the updater and return\n                attrs_updater\n                    .take()\n                    .expect(\"attrs_updater should only be called once\")(attrs);\n\n                // Record the status of the span from the attrs themselves\n                if let Some(status) = attrs.get_span_status() {\n                    span_ext_mut.replace(status);\n                }\n\n                return;\n            }\n        }\n    });\n}\n\n/// Reads span start info from the given span with read-only access.\n///\n/// This provides immutable access to the span's start information including\n/// trace_id, span_id, span_name, and other metadata.\n///\n/// Returns `None` if span is disabled.","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-tracing/src/span_info.rs#L413-L449","documentation":"Panic from `.expect()` after `attrs_updater.take()` in `find_and_record_span_status_from_attrs`. The updater is passed as `Option<impl FnOnce>` and must be consumed exactly once; a `None` here means the function's internal calling convention was violated (updater already taken or never supplied).","triggerScenarios":"Calling `find_and_record_span_status_from_attrs` with a `None` updater, or a code path that invokes the function twice reusing the same consumed updater Option — only reachable through an internal caller bug since the public wrappers always construct the updater.","commonSituations":"Custom forks or patched call sites that pass `None` or double-call the function; refactors that moved the `take()` call without preserving the exactly-once contract.","solutions":["Ensure every call to `find_and_record_span_status_from_attrs` supplies a fresh `Some(updater)` closure.","Audit the calling path (`record_test_span_with_detail`, `execute_unit_test_remote`, `process_unit_test_result`) for double invocation of the same updater value.","If hit after a refactor, restructure so the updater is moved into the function rather than shared."],"exampleFix":"// before\nfind_and_record_span_status_from_attrs(span, None);\n\n// after\nfind_and_record_span_status_from_attrs(span, Some(Box::new(|attrs| { attrs.set_status(...); })));","handlingStrategy":"validation","validationCode":"// assert updater supplied exactly once before calling\nassert!(attrs_updater.is_some(), \"updater must be Some\");\nfind_and_record_span_status_from_attrs(span, attrs_updater);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the updater as `impl FnOnce` moved into the call so the compiler enforces single use.","Never reuse an `Option< updater >` across two invocations.","Keep the function private if the exactly-once contract is internal."],"tags":["telemetry","tracing","panic","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}