{"record":{"id":"e8f13afcca202c9f","repo":"serde-rs/json","slug":"number-value-was-not-emitted","errorCode":null,"errorMessage":"number value was not emitted","messagePattern":"number value was not emitted","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/value/ser.rs","lineNumber":686,"sourceCode":"            }\n            #[cfg(feature = \"raw_value\")]\n            SerializeMap::RawValue { out_value } => {\n                if key == crate::raw::TOKEN {\n                    *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)));","sourceCodeStart":668,"sourceCodeEnd":704,"githubUrl":"https://github.com/serde-rs/json/blob/afdf6fc67247dd7fa4fcde1381e6ecc6bcc7a30e/src/value/ser.rs#L668-L704","documentation":"With the arbitrary_precision feature, serde_json::Number serializes itself via a private struct protocol: Number::serialize (src/number.rs:392) calls serialize_struct(\"$serde_json::private::Number\", 1) then serialize_field(\"$serde_json::private::Number\", &self.n). The value Serializer routes that struct name to SerializeMap::Number { out_value: None } (src/value/ser.rs:274), and serialize_field sets out_value = Some(...). The panic at src/value/ser.rs:686 fires in end() when out_value is still None — i.e. the required single field was never emitted. This is an internal invariant guarding serde_json's own Number round-trip; the constant TOKEN is defined at src/number.rs:18.","triggerScenarios":"Code that manually calls serializer.serialize_struct(\"$serde_json::private::Number\", 1) (copying serde_json's private TOKEN) against the to_value / value::Serializer and then calls end() without a matching serialize_field(\"$serde_json::private::Number\", ...), or with the field key misspelled (the equality check is at src/value/ser.rs:662). A generic Serialize wrapper/adapter that forwards the struct name but drops or renames the field. A serde version skew where a downstream crate hardcodes an old/new TOKEN string that no longer matches crate::number::TOKEN. Not reachable through normal public API usage (to_value, to_string, derived Serialize) because Number::serialize always emits the field.","commonSituations":"A crate that tries to interoperate with serde_json's arbitrary_precision representation by reconstructing the magic struct instead of using serde_json::Number. Copy-pasting the private constant $serde_json::private::Number from serde_json source or docs. Upgrading serde_json across a version that changed/clarified the TOKEN and finding a hand-maintained mirror now diverges. Fuzzing or property-testing a custom Serializer against serde_json's value Serializer with arbitrary struct names that happen to collide.","solutions":["Stop reconstructing the private $serde_json::private::Number protocol; use the public serde_json::Number API (Number::from_str / from_i64 / from_f64 / serialize) so the field is always emitted correctly.","If you are writing a Serializer that must honor the protocol, ensure serialize_struct with that name is always followed by exactly one serialize_field with the same key before end().","Remove any hardcoded copy of the TOKEN string; if you must reference it, keep it in lockstep with the serde_json version you depend on, or avoid the protocol entirely.","Reproduce in isolation with serde_json::to_value on your type (arbitrary_precision enabled) to confirm the field path is taken, then drop the manual mirror.","Pin and audit serde_json versions across your workspace so the TOKEN contract does not silently drift."],"exampleFix":"// before — reconstructing serde_json's private Number protocol\nlet name = \"$serde_json::private::Number\";\nlet mut s = serializer.serialize_struct(name, 1)?;\n// forgot the field, or used a wrong key -> end() panics: number value was not emitted\ns.end()\n\n// after — use the public API; Number emits the field itself\nlet n: serde_json::Number = serde_json::Number::from_str(\"123456789012345678901234567890\")\n    .map_err(serde::ser::Error::custom)?;\nn.serialize(serializer)","handlingStrategy":"validation","validationCode":"// No pre-call runtime check prevents this; it fires inside end() for the\n// private $serde_json::private::Number struct protocol. The only safe input\n// is a real serde_json::Number. If you must accept serialized numbers, build\n// them through the public API:\nfn make_number(s: &str) -> Result<serde_json::Number, serde_json::Error> {\n    // validates the representation used by arbitrary_precision round-trips\n    serde_json::Number::from_str(s).ok_or_else(|| {\n        serde::de::Error::custom(\"invalid number literal\")\n    })\n}","typeGuard":"// Not applicable: the panic is an internal-contract violation keyed on a\n// private struct name, not a type you can narrow at the call site.","tryCatchPattern":"// Fix the producer; do not catch. If isolating an untrusted serializer:\nlet res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    serde_json::to_value(&value_with_custom_serialize)\n}));\nif res.is_err() {\n    // number value was not emitted — stop reconstructing the TOKEN protocol\n}","preventionTips":["Never hardcode \"$serde_json::private::Number\" as a struct name; use serde_json::Number.","If you implement a Serializer honoring the protocol, always emit the field before end().","Keep serde_json version pinned and audited so the TOKEN contract cannot drift.","Add a test that round-trips Number through to_value with arbitrary_precision enabled.","Search your dependency tree for copies of the private TOKEN string."],"tags":["serde-json","number","arbitrary-precision","serialize","panic","internal-contract","private-api"],"backgroundTag":null,"analyzedSha":"afdf6fc67247dd7fa4fcde1381e6ecc6bcc7a30e","analyzedAt":"2026-08-08T07:08:57.171Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}