zed-industries/zed · error
failed to add stream output
Error message
failed to add stream output: {} What it means
macOS ScreenCaptureKit rejected the attempt to attach the screen output to an SCStream. When `addStreamOutput:type:sampleHandlerQueue:error:` fails, the capture stream cannot deliver frames, so the error (a localizedDescription from the ObjC layer) is surfaced as an anyhow error through the async channel.
Solutions
- Grant Screen Recording permission to the app in System Settings > Privacy & Security > Screen Recording and relaunch
- Check the localizedDescription in the message for the specific ScreenCaptureKit error
- Verify SCStream configuration (width/height/pixel format) is valid for the target display
- Ensure the app runs in an environment with a display and required entitlements
Example fix
// before
if let Err(error) = stream.addStreamOutput_type_sampleHandlerQueue_error(...) { /* send error */ }
// after
if let Err(error) = stream.addStreamOutput_type_sampleHandlerQueue_error(...) {
_ = sender.send(Err(anyhow!("failed to add stream output: {}; check Screen Recording permission", error.localizedDescription())));
return receiver;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check screen recording permission (macOS 15+)
let granted = CGPreflightScreenCaptureAccess();
if !granted { panic!("Screen Recording permission required"); } Type guard
fn stream_output_added(result: &Result<Receiver, anyhow::Error>) -> bool { result.is_ok() } Try / catch
let receiver = capture::stream(...);
while let Some(event) = receiver.recv().await {
if let Err(e) = event {
if e.to_string().contains("failed to add stream output") {
prompt_screen_recording_permission();
break;
}
}
} Prevention
- Request Screen Recording permission before initializing capture
- Test capture on the minimum supported macOS version for ScreenCaptureKit
- Validate stream configuration dimensions against the display
- Handle the empty frame stream gracefully when TCC denies access
When it happens
Trigger: Calling `stream()` in gpui_macos's screen_capture when SCStream output setup fails — e.g. screen recording permission not granted, invalid stream configuration, or the stream was already torn down.
Common situations: First-run without Screen Recording permission in System Settings (TCC denial), running in environments without a display/entitlements, or macOS version where ScreenCaptureKit APIs changed.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Screen share failed
- error running osascript
- failed to start screen capture stream
- Screen share failed
- agent.tool_permissions should be an object or null when…
AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19).
Data as JSON: /api/errors/92a91f06990a7e39.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gpui_macos/src/screen_capture.rs:98
configuration.setPixelFormat(0x42475241);
configuration.setWidth(metadata.resolution.width.0 as usize);
configuration.setHeight(metadata.resolution.height.0 as usize);
let stream = SCStream::initWithFilter_configuration_delegate(
SCStream::alloc(),
&filter,
&configuration,
None,
);
let output = StreamOutput::new(frame_callback);
let output_protocol = ProtocolObject::from_ref(&*output);
if let Err(error) = stream.addStreamOutput_type_sampleHandlerQueue_error(
output_protocol,
SCStreamOutputType::Screen,
None,
) {
_ = sender.send(Err(anyhow!(
"failed to add stream output: {}",
error.localizedDescription()
)));
return receiver;
}
let state = Rc::new(RefCell::new(Some((sender, stream.clone(), output))));
let handler = RcBlock::new(move |error: *mut NSError| {
let Some((sender, stream, output)) = state.borrow_mut().take() else {
return;
};
let result = if let Some(error) = error.as_ref() {
Err(anyhow!(
"failed to start screen capture stream: {}",
error.localizedDescription()
))
} else {View on GitHub (pinned to 916fc2b8cb)