Is there an existing issue for this?
What version of workers-rs are you using?
0.8.4
What version of wrangler are you using?
4.100.0
Describe the bug
Summary
In worker 0.8.x, Queue::send defaults outgoing messages to content_type = Json. A consumer written against the 0.7.x default (which delivered a structured-clone object body) silently drops these messages: send() returns Ok, the consumer batch returns Ok, no exception, no log, zero messages processed. During a gradual upgrade — or when one queue is shared by services on different worker versions — this breaks invisibly.
Environment
worker 0.8.4 producer interoperating with a 0.7.x consumer over a Cloudflare Queue.
wasm32-unknown-unknown, Rust 1.96, worker-build 0.8.4.
Where it comes from
impl<T: Serialize> From<T> for SendMessage<T> hard-codes the default:
// worker-0.8.4/src/queue.rs
impl<T: Serialize> From<T> for SendMessage<T> {
fn from(message: T) -> Self {
Self { message, options: Some(QueueSendOptions {
content_type: Some(QueueContentType::Json), // <-- default (was v8 in 0.7.x)
delay_seconds: None,
})}
}
}
A consumer expecting the old structured-clone object typically does:
let body = raw_message.body(); // JsValue
if !body.is_object() { continue; } // a `json`-typed body fails this → SILENTLY skipped
Why this was painful
The wire format changed across a minor-version bump with no error and no obvious note. It took a long debugging session to find, because every layer reports success.
Asks
- Call out the default-
content_type change prominently in the CHANGELOG / a 0.7→0.8 migration note — it's a wire-format behavior change, not just an API change.
- Consider keeping the prior default, or at least making the default a clearly-documented, pinnable constant, with a note that producer and consumer must agree on
content_type.
- Optionally: give consumers a way to detect a
content_type their decoder didn't expect, instead of silently yielding a non-object body.
Steps To Reproduce
- Producer (0.8.x):
queue.send(MyMsg { .. }).await? — default content_type = Json.
- Consumer (0.7.x, or anything expecting a structured-clone object):
if !body.is_object() { continue }.
- Observe: producer
Ok, consumer Ok, 0 messages processed, no error anywhere.
Workaround (producer side):
queue.send(MessageBuilder::new(msg).content_type(QueueContentType::V8).build()).await?;
Related to #1013
Is there an existing issue for this?
What version of
workers-rsare you using?0.8.4
What version of
wranglerare you using?4.100.0
Describe the bug
Summary
In
worker0.8.x,Queue::senddefaults outgoing messages tocontent_type = Json. A consumer written against the 0.7.x default (which delivered a structured-clone object body) silently drops these messages:send()returnsOk, the consumer batch returnsOk, no exception, no log, zero messages processed. During a gradual upgrade — or when one queue is shared by services on differentworkerversions — this breaks invisibly.Environment
worker0.8.4 producer interoperating with a 0.7.x consumer over a Cloudflare Queue.wasm32-unknown-unknown, Rust 1.96,worker-build 0.8.4.Where it comes from
impl<T: Serialize> From<T> for SendMessage<T>hard-codes the default:A consumer expecting the old structured-clone object typically does:
Why this was painful
The wire format changed across a minor-version bump with no error and no obvious note. It took a long debugging session to find, because every layer reports success.
Asks
content_typechange prominently in the CHANGELOG / a 0.7→0.8 migration note — it's a wire-format behavior change, not just an API change.content_type.content_typetheir decoder didn't expect, instead of silently yielding a non-object body.Steps To Reproduce
queue.send(MyMsg { .. }).await?— defaultcontent_type = Json.if !body.is_object() { continue }.Ok, consumerOk, 0 messages processed, no error anywhere.Workaround (producer side):
Related to #1013