GyulyVGC/sniffnet · error · serde::de::Error
a Service enum
Error message
a Service enum
What it means
The custom Deserialize impl for the Service enum (src/networking/types/service.rs:27) implements expecting() with the text 'a Service enum'. Serde invokes this message whenever the deserializer encounters input of the wrong shape — e.g. a JSON string, number, or map where an enum ("Name", "Unknown", "NotApplicable" variants) is required — producing errors like 'invalid type: string "https", expected a Service enum'. The manual impl exists to Box::leak the Name payload into a &'static str for cheap storage.
Source
Thrown at src/networking/types/service.rs:27
/// Not identified
#[default]
Unknown,
/// Not applicable
NotApplicable,
}
impl<'de> Deserialize<'de> for Service {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ServiceVisitor;
impl<'de> de::Visitor<'de> for ServiceVisitor {
type Value = Service;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a Service enum")
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: de::EnumAccess<'de>,
{
let (variant, access) = data.variant::<String>()?;
match variant.as_str() {
"Name" => {
let s: String = access.newtype_variant()?;
let leaked: &'static str = Box::leak(s.into_boxed_str());
Ok(Service::Name(leaked))
}
"Unknown" => {
access.unit_variant()?;
Ok(Service::Unknown)
}
"NotApplicable" => {View on GitHub (pinned to 48b0575dc0)
Solutions
- Emit the enum in serde's externally tagged form: known service as object {"Name":"https"}, the others as bare strings "Unknown" / "NotApplicable".
- Round-trip via Service's own Serialize to learn the exact accepted shape: serde_json::to_string(&Service::Name("https")) → {"Name":"https"}.
- Validate upstream JSON against that shape (JSON Schema or a pre-parse check) before from_str.
- If you control both ends and want untagged strings, deserialize into a String/serde_json::Value first and map to Service manually.
Example fix
// before — wrong shape: bare string payload where enum expected
let s: Service = serde_json::from_str("\"https\"")?; // invalid type: expected a Service enum
// after — serde's externally tagged enum representation
let s: Service = serde_json::from_str("{\"Name\":\"https\"}")?; // Service::Name("https")
let u: Service = serde_json::from_str("\"Unknown\"")?; // Service::Unknown
let n: Service = serde_json::from_str("\"NotApplicable\"")?; // Service::NotApplicable Defensive patterns
Strategy: type-guard
Validate before calling
// shape-check raw JSON before parsing into Service
fn service_shape_ok(v: &serde_json::Value) -> bool {
match v {
serde_json::Value::String(s) => matches!(s.as_str(), "Unknown" | "NotApplicable"),
serde_json::Value::Object(m) => m.len() == 1 && m.get("Name").is_some_and(|n| n.is_string()),
_ => false,
}
} Type guard
fn is_service_shaped(v: &serde_json::Value) -> bool {
match v {
serde_json::Value::String(s) => matches!(s.as_str(), "Unknown" | "NotApplicable"),
serde_json::Value::Object(m) => {
m.len() == 1 && matches!(m.keys().next().map(String::as_str), Some("Name"))
&& m["Name"].is_string()
}
_ => false,
}
} Try / catch
// catch shape errors with position context
match serde_json::from_str::<Service>(raw) {
Ok(s) => Ok(s),
Err(e) if e.to_string().contains("expected a Service enum") => {
Err(format!("bad Service shape at {}: {raw}", e))
}
Err(e) => Err(e.to_string()),
} Prevention
- Learn the accepted wire form by round-tripping: serde_json::to_string(&Service::Name("https")) → {"Name":"https"}.
- Generate producer JSON with Service's own Serialize instead of hand-writing shapes.
- Validate payloads with a JSON Schema (or the type guard above) before deserializing.
- Keep serialized data and enum definition in the same version of the codebase.
When it happens
Trigger: Deserializing (serde_json::from_str::<Service> or any format driven by the Deserialize impl) data whose JSON shape is not an enum representation of Service: `"https"` (bare string) instead of `{"Name":"https"}` / `"Name"`-style tagged values, `42`, `null`, `{"Name":123}` (non-string payload), or a map with multiple entries where a newtype variant is expected.
Common situations: Hand-edited or machine-generated JSON consumed by tooling built on Sniffnet's types (e.g. analysis output, reports) where the service field was serialized differently than Sniffnet's Serialize derives (externally tagged enum: {"Name":"https"}, "Unknown", "NotApplicable"); version changes that altered the wire shape; feeding an array of strings from another tool into a field typed Service.
Related errors
- unknown variant {other}, expected one of `Name`, `Unknown`,
- Sniffnet error at [{file}:{line}]: {e}
- panic!() (bare panic triggered by ErrorLogger on Err in debu
- Could not restore default settings
- Could not retrieve configuration file path
AI-assisted analysis of GyulyVGC/sniffnet@48b0575dc0 (2026-08-16).
Data as JSON: /api/errors/5892365b4bf05b96.
Report an issue: GitHub.