BloopAI/vibe-kanban · error

Raw stream should only have Stdout/Stderr/Finished

Error message

Raw stream should only have Stdout/Stderr/Finished

What it means

In handle_raw_logs_ws, the raw execution-process log stream is mapped to WebSocket messages. Only Stdout, Stderr, and Finished are expected from the raw channel; any other LogMsg variant hits `unreachable!("Raw stream should only have Stdout/Stderr/Finished")`. This asserts the raw log channel's contract — e.g. if the upstream log source starts emitting JsonPatch or other control variants, the handler panics.

Source

Thrown at crates/server/src/routes/execution_processes.rs:102

        }
    };

    let counter = Arc::new(AtomicUsize::new(0));
    let mut stream = raw_stream.map_ok({
        let counter = counter.clone();
        move |m| match m {
            LogMsg::Stdout(content) => {
                let index = counter.fetch_add(1, Ordering::SeqCst);
                let patch = ConversationPatch::add_stdout(index, content);
                LogMsg::JsonPatch(patch).to_ws_message_unchecked()
            }
            LogMsg::Stderr(content) => {
                let index = counter.fetch_add(1, Ordering::SeqCst);
                let patch = ConversationPatch::add_stderr(index, content);
                LogMsg::JsonPatch(patch).to_ws_message_unchecked()
            }
            LogMsg::Finished => LogMsg::Finished.to_ws_message_unchecked(),
            _ => unreachable!("Raw stream should only have Stdout/Stderr/Finished"),
        }
    });

    loop {
        tokio::select! {
            item = stream.next() => {
                match item {
                    Some(Ok(msg)) => {
                        if socket.send(msg).await.is_err() {
                            break;
                        }
                    }
                    Some(Err(e)) => {
                        tracing::error!("stream error: {}", e);
                        break;
                    }
                    None => break,
                }

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Inspect the backtrace/log to identify the unexpected LogMsg variant and either filter it out before mapping or add an explicit arm.
  2. Ensure the raw logs channel is only fed by raw stdout/stderr/finished producers, not the JsonPatch-producing normalized stream.
  3. Replace the wildcard `_` arm with an explicit enumeration so compilation fails when new LogMsg variants are added.

Example fix

// before
_ => unreachable!("Raw stream should only have Stdout/Stderr/Finished"),
// after
LogMsg::JsonPatch(_) => continue, // or handle explicitly
_ => unreachable!("Raw stream should only have Stdout/Stderr/Finished"),
Defensive patterns

Strategy: try-catch

Validate before calling

// Producer side: only emit raw variants
assert!(matches!(msg, LogMsg::Stdout(_)|LogMsg::Stderr(_)|LogMsg::Finished));

Try / catch

match log_msg {
  LogMsg::Stdout(_) | LogMsg::Stderr(_) | LogMsg::Finished => { /* map */ }
  other => {
    tracing::warn!("unexpected raw log variant: {:?}", other);
    // skip instead of panicking
  }
}

Prevention

When it happens

Trigger: A LogMsg arrives on the raw logs stream that is not Stdout/Stderr/Finished — e.g. the log broadcaster emits JsonPatch or control messages on the raw channel, or a new LogMsg variant was added without updating this mapping.

Common situations: Executor changes that route structured (JsonPatch) output through the raw stream; a shared log channel reused for both normalized and raw subscribers; adding a LogMsg variant upstream without touching this endpoint.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/f0084fd1b66c8c2f. Report an issue: GitHub.