{"record":{"id":"d1d0e292033e36d9","repo":"vectordotdev/vector","slug":"early-buffer-was-already-consumed","errorCode":null,"errorMessage":"early buffer was already consumed","messagePattern":"early buffer was already consumed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/trace.rs","lineNumber":193,"sourceCode":"\n/// Attempts to broadcast an event to subscribers.\n///\n/// If no subscribers are connected, this does nothing.\nfn try_broadcast_event(log: LogEvent) {\n    if let Some(sender) = maybe_get_trace_sender() {\n        _ = sender.send(log);\n    }\n}\n\n/// Consumes the early buffered events.\n///\n/// # Panics\n///\n/// If the early buffered events have already been consumed, this function will panic.\nfn consume_early_buffer() -> Vec<LogEvent> {\n    get_early_buffer()\n        .take()\n        .expect(\"early buffer was already consumed\")\n}\n\n/// Gets or creates a trace sender for sending internal log events.\nfn get_trace_sender() -> &'static broadcast::Sender<LogEvent> {\n    SENDER.get_or_init(|| broadcast::channel(99).0)\n}\n\n/// Attempts to get the trace sender for sending internal log events.\n///\n/// If the trace sender has not yet been created, `None` is returned.\nfn maybe_get_trace_sender() -> Option<&'static broadcast::Sender<LogEvent>> {\n    SENDER.get()\n}\n\n/// Creates a trace receiver that receives internal log events.\n///\n/// This will create a trace sender if one did not already exist.\nfn get_trace_receiver() -> broadcast::Receiver<LogEvent> {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/src/trace.rs#L175-L211","documentation":"`consume_early_buffer` takes the buffered early log events out of the static BUFFER via `.take()`. `take()` returns `None` if the buffer is already `None`, meaning the early buffer was consumed once before; the `expect` then panics. Per its doc comment, consuming twice is a caller-contract violation.","triggerScenarios":"Calling `consume_early_buffer` (through `stop_early_buffering`) more than once — e.g. `stop_early_buffering` invoked twice, or after early buffering was already stopped and consumed.","commonSituations":"Duplicate shutdown/initialization sequences in tests that call `stop_early_buffering` per test without isolation; race conditions where two tasks both attempt to stop early buffering concurrently.","solutions":["Ensure `stop_early_buffering` is called exactly once per process lifetime","Guard the stop call with an idempotency check (e.g. a OnceLock/atomic flag)","Use `consume_early_buffer`'s caller contract: check `should_process_tracing_event`/buffer state before consuming","In tests, run each case in a separate process or serialize setup"],"exampleFix":"// before\nstop_early_buffering();\nstop_early_buffering(); // panics\n// after\nstatic STOPPED: OnceLock<()> = OnceLock::new();\nif STOPPED.set(()).is_ok() {\n    stop_early_buffering();\n}","handlingStrategy":"validation","validationCode":"// idempotent guard around consume\nstatic CONSUMED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);\nif !CONSUMED.swap(true, std::sync::atomic::Ordering::SeqCst) {\n    stop_early_buffering();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call stop_early_buffering exactly once per process","Use OnceLock/atomic flags for idempotency","Serialize shutdown logic; avoid concurrent stop calls","Isolate per-test tracing state"],"tags":["rust","panic","tracing","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}