{"record":{"id":"a6129c9e6835f239","repo":"serde-rs/json","slug":"raw-value-was-not-emitted","errorCode":null,"errorMessage":"raw value was not emitted","messagePattern":"raw value was not emitted","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/value/ser.rs","lineNumber":690,"sourceCode":"                    *out_value = Some(tri!(value.serialize(RawValueEmitter)));\n                    Ok(())\n                } else {\n                    Err(invalid_raw_value())\n                }\n            }\n        }\n    }\n\n    fn end(self) -> Result<Value> {\n        match self {\n            SerializeMap::Map { .. } => serde::ser::SerializeMap::end(self),\n            #[cfg(feature = \"arbitrary_precision\")]\n            SerializeMap::Number { out_value, .. } => {\n                Ok(out_value.expect(\"number value was not emitted\"))\n            }\n            #[cfg(feature = \"raw_value\")]\n            SerializeMap::RawValue { out_value, .. } => {\n                Ok(out_value.expect(\"raw value was not emitted\"))\n            }\n        }\n    }\n}\n\nimpl serde::ser::SerializeStructVariant for SerializeStructVariant {\n    type Ok = Value;\n    type Error = Error;\n\n    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>\n    where\n        T: ?Sized + Serialize,\n    {\n        self.map.insert(String::from(key), tri!(to_value(value)));\n        Ok(())\n    }\n\n    fn end(self) -> Result<Value> {","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/serde-rs/json/blob/afdf6fc67247dd7fa4fcde1381e6ecc6bcc7a30e/src/value/ser.rs#L672-L708","documentation":"With the raw_value feature, serde_json::RawValue serializes itself via the same private struct protocol as Number: RawValue::serialize calls serialize_struct(\"$serde_json::private::RawValue\", 1) then serialize_field(\"$serde_json::private::RawValue\", &self.json). The value Serializer routes that name to SerializeMap::RawValue { out_value: None } (src/value/ser.rs:276), and the field sets out_value = Some(...). The panic at src/value/ser.rs:690 fires in end() when out_value is still None — the required raw-JSON field was never emitted. The constant TOKEN lives at src/raw.rs:342. Like error 2, this guards an internal round-trip invariant and is not reachable through normal public usage.","triggerScenarios":"Code that manually calls serializer.serialize_struct(\"$serde_json::private::RawValue\", 1) against the to_value / value::Serializer and then calls end() without a matching serialize_field(\"$serde_json::private::RawValue\", ...) (key equality checked at src/value/ser.rs:671). A Serialize wrapper/adapter that forwards the struct name but drops, reorders, or renames the field. Version skew where a downstream crate hardcodes a TOKEN string that no longer matches crate::raw::TOKEN. Not reachable through serde_json::to_value/to_string on a real RawValue, because RawValue::serialize always emits the field.","commonSituations":"A crate implementing a JSON-passthrough or buffered serializer that mirrors serde_json's RawValue magic struct instead of using serde_json::value::RawValue. Copying the constant $serde_json::private::RawValue from serde_json internals/docs into a custom Serialize impl. Upgrading serde_json and finding a hand-maintained mirror diverges from the canonical TOKEN. Building a generic Serializer test harness that feeds arbitrary struct names, one of which collides with the RawValue TOKEN.","solutions":["Stop reconstructing the private $serde_json::private::RawValue protocol; use serde_json::value::RawValue (and its from_str / serialize) so the field is always emitted correctly.","If you implement a Serializer that must honor the protocol, guarantee serialize_struct with that name is followed by exactly one serialize_field with the identical key before end().","Delete any hardcoded copy of the TOKEN string; depend on serde_json's public RawValue instead of mirroring internals.","Reproduce with serde_json::to_value on a real RawValue (raw_value enabled) to confirm the happy path, then remove the manual mirror.","Pin and audit serde_json versions across the workspace so the RawValue TOKEN contract does not silently drift."],"exampleFix":"// before — reconstructing serde_json's private RawValue protocol\nlet name = \"$serde_json::private::RawValue\";\nlet mut s = serializer.serialize_struct(name, 1)?;\n// forgot the field, or used a wrong key -> end() panics: raw value was not emitted\ns.end()\n\n// after — use the public RawValue API; it emits the field itself\nuse serde_json::value::RawValue;\nlet raw: &RawValue = serde_json::from_str(\"{\\\"x\\\":1}\")?;\nraw.serialize(serializer)","handlingStrategy":"validation","validationCode":"// No runtime pre-check exists; the panic is internal to the\n// $serde_json::private::RawValue struct protocol. Accept raw JSON only via\n// the public RawValue type so the field is always emitted:\nfn make_raw(json: &str) -> Result<Box<serde_json::value::RawValue>, serde_json::Error> {\n    serde_json::value::RawValue::from_string(json.to_owned())\n}","typeGuard":"// Not applicable: the panic is keyed on a private struct name inside the\n// value Serializer, not a caller-narrowable type.","tryCatchPattern":"// Fix the producer; catch_unwind only isolates untrusted code:\nlet res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    serde_json::to_value(&value_with_custom_serialize)\n}));\nif res.is_err() {\n    // raw value was not emitted — stop reconstructing the TOKEN protocol\n}","preventionTips":["Never hardcode \"$serde_json::private::RawValue\" as a struct name; use serde_json::value::RawValue.","If you implement a Serializer honoring the protocol, always emit the field before end().","Pin and audit serde_json versions across the workspace.","Test RawValue round-trips through to_value with raw_value enabled.","Audit dependencies for vendored copies of the private TOKEN string."],"tags":["serde-json","raw-value","serialize","panic","internal-contract","private-api"],"backgroundTag":null,"analyzedSha":"afdf6fc67247dd7fa4fcde1381e6ecc6bcc7a30e","analyzedAt":"2026-08-08T07:08:57.171Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}