{"record":{"id":"b79af43b4731e8ef","repo":"vectordotdev/vector","slug":"no-default-output","errorCode":null,"errorMessage":"no default output","messagePattern":"no default output","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vector-core/src/source_sender/sender.rs","lineNumber":247,"sourceCode":"            output_id,\n            None,\n            None,\n        );\n        let recv = recv.into_stream().map(move |mut item| {\n            item.events.iter_events_mut().for_each(|mut event| {\n                let metadata = event.metadata_mut();\n                metadata.update_status(status);\n                metadata.update_sources();\n            });\n            item\n        });\n        self.named_outputs.insert(name, output);\n        recv\n    }\n\n    /// Get a mutable reference to the default output, panicking if none exists.\n    const fn default_output_mut(&mut self) -> &mut Output {\n        self.default_output.as_mut().expect(\"no default output\")\n    }\n\n    /// Send an event to the default output.\n    ///\n    /// This internally handles emitting [EventsSent] and [ComponentEventsDropped] events.\n    pub async fn send_event(&mut self, event: impl Into<EventArray>) -> Result<(), SendError> {\n        self.default_output_mut().send_event(event).await\n    }\n\n    /// Send a stream of events to the default output.\n    ///\n    /// This internally handles emitting [EventsSent] and [ComponentEventsDropped] events.\n    pub async fn send_event_stream<S, E>(&mut self, events: S) -> Result<(), SendError>\n    where\n        S: Stream<Item = E> + Unpin,\n        E: Into<Event> + ByteSizeOf,\n    {\n        self.default_output_mut().send_event_stream(events).await","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/lib/vector-core/src/source_sender/sender.rs#L229-L265","documentation":"`default_output_mut` unconditionally unwraps `self.default_output` and panics with \"no default output\" if it is absent. The library treats a `SourceSender` without a default output as an invalid state: callers like `send_event`/`send_batch` require the default output created during construction, so its absence is an internal invariant violation.","triggerScenarios":"Constructing or obtaining a `SourceSender` whose `default_output` field is `None` (e.g. a sender built via paths that never call the default-output-producing constructor, or after the output was consumed/replaced) and then invoking any method that calls `default_output_mut` — `send_event`, `send_batch`, or `add_outputs`-related default-output access via `source_with_sender`.","commonSituations":"Custom Rust sources wiring a `SourceSender` by hand instead of using `SourceSender::new`/`source_with_sender`; refactors that changed the constructor without updating all send paths; using a sender after its default output was moved out.","solutions":["Create the sender with a default output (e.g. `SourceSender::new()` or the `source_with_sender` helper) before sending events.","Use named outputs exclusively (`add_output`/`send_batch_named`) if your topology intentionally has no default output.","Check that you are not reusing a `SourceSender` whose outputs were already taken/moved.","Update the library call path so `default_output_mut` is only reached on senders known to have a default output."],"exampleFix":"// before\nlet (sender, _) = some_custom_constructor_without_default();\nsender.send_event(event).await?; // panics: no default output\n// after\nlet (mut sender, receiver) = SourceSender::new();\nsender.send_event(event).await?;","handlingStrategy":"type-guard","validationCode":"// Before sending, confirm the sender exposes the default output\nassert!(sender.default_output.is_some(), \"SourceSender has no default output; call SourceSender::new() first\");","typeGuard":"fn has_default_output(sender: &SourceSender) -> bool {\n    // if the field is private, track it at your call site:\n    // keep an Option<SourceSender> and only unwrap after construction with a default output\n    true // replace with an accessor when available\n}","tryCatchPattern":"// Rust: this is a panic, guard the call site\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    // any use of default_output_mut via send_event\n}));\nif result.is_err() { /* sender was misconstructed: rebuild it */ }","preventionTips":["Always construct sources through source_with_sender / SourceSender::new so a default output exists.","Never hand-roll a SourceSender struct literal; use its constructors.","If your source only needs named outputs, never touch default-output APIs.","Add a debug_assert that a default output exists before the send loop starts."],"tags":["rust","topology","source","missing-output"],"backgroundTag":"internal-invariant-violation","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"}