Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- `fleet spawn` and SDK placement no longer report `dispatchState: "dispatched"` for a spawn that was placed but never sent. Only `dispatched_node_id`, or a status the node moved, counts as dispatch evidence, so `fleet spawn` and `fleet spawn-status` agree.
- When a broker worker fails to spawn, the log now includes the underlying OS error, such as a missing binary, instead of only `failed to spawn worker`.

## [13.4.1] - 2026-10-12

Expand Down
23 changes: 21 additions & 2 deletions crates/broker/src/runtime/relaycast_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,18 +1125,37 @@ pub(super) async fn spawn_worker_from_request(
if msg.contains("already exists") {
tracing::debug!(child = %name, "agent already spawned via SDK, skipping duplicate relaycast WS spawn");
} else {
tracing::error!(child = %name, error = %e, "failed to spawn worker via relaycast WS");
eprintln!("[agent-relay] failed to spawn '{}': {}", name, e);
let detail = spawn_failure_detail(&e);
tracing::error!(child = %name, error = %detail, "failed to spawn worker via relaycast WS");
eprintln!("[agent-relay] failed to spawn '{}': {}", name, detail);
}
Err(e)
}
}
}

/// The whole error chain. Display alone stops at the outermost context
/// ("failed to spawn worker") and drops the OS error that says why.
fn spawn_failure_detail(error: &anyhow::Error) -> String {
format!("{error:#}")
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn spawn_failure_detail_keeps_the_os_error() {
let error = anyhow::Error::new(std::io::Error::from(std::io::ErrorKind::NotFound))
.context("failed to spawn worker");
let detail = spawn_failure_detail(&error);
assert!(detail.starts_with("failed to spawn worker: "), "{detail}");
assert!(
detail.contains(&std::io::Error::from(std::io::ErrorKind::NotFound).to_string()),
"{detail}"
);
}

#[test]
fn duplicate_registration_keeps_already_exists_for_debug_log_classification() {
let error = ::relaycast::AgentRegistrationError::AlreadyExists {
Expand Down
Loading