Workflow send_message cannot target a different channel; runs fail silently
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
A workflow whose `send_message` step targets a **different channel** than the one the workflow is bound to always fails. The run is created and accepted, then dies at the first step with no user-visible error. From the outside it looks like "workflows silently do nothing."
## Repro
1. Create a workflow in channel A:
```yaml
name: Recycle to Kaizen
trigger:
on: reaction_added
emoji: "♻️"
steps:
- id: post_candidate
action: send_message
channel:
text: "## Flagged for Kaizen"
enabled: true
```
2. `buzz workflows trigger --workflow ` → `{"accepted": true, "run_id": "..."}`
3. Nothing is ever posted to channel B, and nothing is posted to channel A either.
## Cause
`resolve_send_message_channel` in `crates/buzz-workflow/src/executor.rs:468` rejects any `channel:` override that differs from the workflow's own `channel_id`:
```rust
if override_channel_id != workflow_channel_id {
return Err(WorkflowError::InvalidDefinition(format!(
"SendMessage: channel override must match the workflow channel ({workflow_channel_id})"
)));
}
```
Since every channel-created workflow has `workflow_channel_id = Some(...)`, the `channel:` field is effectively **write-only** — it can only ever name the channel it already posts to. Cross-channel routing is impossible.
## Why this is worse than a missing feature
The `channel:` key is accepted at create time by the schema and by Desktop's workflow form. There is no validation error, no warning, and no run-history surface (see the related issue on run visibility), so the failure is invisible at every layer. Three separate debugging sessions on my side concluded "workflow steps don't execute at all" before reading the source.
## Requested
Either:
- **(preferred)** allow `send_message` to target any channel the workflow **owner** is a member of, authorizing on owner membership rather than on workflow binding; or
- reject the workflow at **create/update time** with a clear error if `channel:` differs from the workflow channel, so the failure is visible immediately instead of at run time.
Cross-channel routing is the core of most useful reaction workflows — "react with an emoji, file it into the triage channel." Without it `reaction_added` can only echo into the channel it fired in.
Contributor guide
Assessment
This issue has not been assessed yet.