dbt-labs/dbt-core · warning · FsError

Generic

Generic

Error message

Failed to detach invocation telemetry layers: {}

What it means

During tracing teardown, the dbt runtime detaches per-invocation telemetry layers via the tracing reload handle. If reload_telemetry(vec![], vec![]) fails, the FsError is collected and reported with this message. It means invocation-scoped log/trace layers could not be removed — usually a symptom of a telemetry-subscriber internal problem, not of user input.

Solutions

  1. Check the interpolated {} detail in the message for the underlying reload failure
  2. Ensure dbt's tracing init/teardown runs exactly once per process invocation
  3. Look for other errors logged before this one during shutdown_items shutdown; fix the root cause there
  4. If seen in tests, isolate subscriber initialization per test or use a serial test harness

Example fix

// before
let mut telemetry = TeardownGuard::new();
let mut telemetry2 = TeardownGuard::new(); // second init corrupts reload handle
// after
let mut telemetry = TeardownGuard::new();
// ... single teardown at process end
telemetry.finish();
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure telemetry is initialized exactly once
static INIT: Once = Once::new();
INIT.call_once(init_dbt_tracing);

Type guard

fn telemetry_active(handle: &ReloadHandle) -> bool { handle.is_initialized() }

Try / catch

if let Err(e) = self.reload_handle.reload_telemetry(vec![], vec![]) {
    log::warn!("telemetry detach failed (non-fatal): {e}");
}

Prevention

When it happens

Trigger: Calling finish() or dropping the teardown guard when the reload handle's subscriber no longer matches the registered layers (already torn down, reinitialized subscriber, or a poisoned reload registry).

Common situations: Double-initialization of the tracing subscriber in the same process (e.g. tests calling dbt init twice); a shutdown ordering bug where layers were already dropped; running under a custom subscriber that replaced dbt's.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/3887cb08a3df2a30. Report an issue: GitHub.

Appendix: source

Thrown at crates/dbt-common/src/tracing/dbt_init.rs:216

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }

    fn teardown(&mut self) -> Vec<FsError> {
        // Set before the work, not after: a panicking shutdown would otherwise be retried
        // during unwinding, and a second panic there aborts the process.
        if self.finished {
            return Vec::new();
        }
        self.finished = true;

        let mut errors: Vec<FsError> = self
            .shutdown_items
            .iter_mut()
            .filter_map(|item| item.shutdown().err().map(FsError::from))
            .collect();

        if let Err(e) = self.reload_handle.reload_telemetry(vec![], vec![]) {
            errors.push(*fs_err!(
                ErrorCode::Generic,
                "Failed to detach invocation telemetry layers: {}",
                e
            ));
        }

        errors
    }
}

impl Drop for InvocationTracingGuard {
    fn drop(&mut self) {
        // Shutting the items down here is load-bearing, not a redundant backstop: the file
        // and parquet writers do flush via their own handles' `Drop`, but OTLP does not —

View on GitHub (pinned to 0267ce9170)