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
The typed queue-consumer path (MessageBatch<T> / Message::try_from(RawMessage)) deserializes each body with serde_wasm_bindgen::from_value. For real-world payloads we found its V8↔serde type coercion unreliable — it produces wrong data or an opaque deserialize error. Bypassing it with JSON.stringify(body) + serde_json::from_str works reliably for the exact same payloads.
Environment
worker 0.8.4, wasm32-unknown-unknown, Rust 1.96.
- Payload: a struct with
serde_json::Values and tuples, e.g. substitutes: Vec<(String, serde_json::Value)>, plus Vec<String>, strings.
Reliable workaround (consumer side)
use js_sys::JSON;
fn parse<T: serde::de::DeserializeOwned>(body: &JsValue) -> Result<T, String> {
let s = JSON::stringify(body).ok().and_then(|s| s.as_string())
.ok_or("JSON.stringify produced no string")?;
serde_json::from_str(&s).map_err(|e| e.to_string())
}
Round-trips through plain JSON and Just Works where serde_wasm_bindgen::from_value mangled the data. (This is also what the previous generation of our consumer hand-rolled — the footgun is long-standing.)
Asks
- Document the limitation + this
JSON.stringify + serde_json escape hatch in the Queues guide — it was the single biggest footgun we hit.
- Consider a
content_type-aware / JSON-based deserialize helper on MessageBatch / Message, e.g. msg.body_json::<T>(), that uses JSON.stringify + serde_json for json-typed bodies instead of serde_wasm_bindgen::from_value.
- More generally: surface the message's
content_type to the consumer so it can choose the right decoder.
Steps To Reproduce
// worker-0.8.4/src/queue.rs
impl<T> TryFrom<RawMessage> for Message<T> where T: DeserializeOwned {
fn try_from(value: RawMessage) -> Result<Self, Error> {
let body = serde_wasm_bindgen::from_value(value.body())?; // <-- V8 coercion
...
}
}
serde_wasm_bindgen's coercion misbehaves on serde_json::Value, tuples (Vec<(String, Value)>), maps, and number / undefined edge cases.
Related to #1012
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
The typed queue-consumer path (
MessageBatch<T>/Message::try_from(RawMessage)) deserializes each body withserde_wasm_bindgen::from_value. For real-world payloads we found its V8↔serde type coercion unreliable — it produces wrong data or an opaque deserialize error. Bypassing it withJSON.stringify(body)+serde_json::from_strworks reliably for the exact same payloads.Environment
worker0.8.4,wasm32-unknown-unknown, Rust 1.96.serde_json::Values and tuples, e.g.substitutes: Vec<(String, serde_json::Value)>, plusVec<String>, strings.Reliable workaround (consumer side)
Round-trips through plain JSON and Just Works where
serde_wasm_bindgen::from_valuemangled the data. (This is also what the previous generation of our consumer hand-rolled — the footgun is long-standing.)Asks
JSON.stringify+serde_jsonescape hatch in the Queues guide — it was the single biggest footgun we hit.content_type-aware / JSON-based deserialize helper onMessageBatch/Message, e.g.msg.body_json::<T>(), that usesJSON.stringify+serde_jsonforjson-typed bodies instead ofserde_wasm_bindgen::from_value.content_typeto the consumer so it can choose the right decoder.Steps To Reproduce
serde_wasm_bindgen's coercion misbehaves onserde_json::Value, tuples (Vec<(String, Value)>), maps, and number /undefinededge cases.Related to #1012