GyulyVGC/sniffnet · error · serde::de::Error

unknown variant {other}, expected one of `Name`, `Unknown`,

Error message

unknown variant {other}, expected one of `Name`, `Unknown`, `NotApplicable`

What it means

In the same manual Service deserializer (src/networking/types/service.rs:49), after reading the variant name, anything other than "Name", "Unknown", or "NotApplicable" raises de::Error::unknown_variant(other, &["Name","Unknown","NotApplicable"]), surfacing as e.g. 'unknown variant `name`, expected one of `Name`, `Unknown`, `NotApplicable`'. This is the strict-variant gate for the leaked-string enum: the set of variants is fixed and case-sensitive.

Source

Thrown at src/networking/types/service.rs:49

            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" => {
                        access.unit_variant()?;
                        Ok(Service::NotApplicable)
                    }
                    other => Err(de::Error::unknown_variant(
                        other,
                        &["Name", "Unknown", "NotApplicable"],
                    )),
                }
            }
        }

        deserializer.deserialize_enum(
            "Service",
            &["Name", "Unknown", "NotApplicable"],
            ServiceVisitor,
        )
    }
}

impl Service {
    pub fn to_string_with_equal_prefix(self) -> String {
        format!("={self}")

View on GitHub (pinned to 48b0575dc0)

Solutions

  1. Use exactly one of the three tags with exact casing: "Name" (with a string payload), "Unknown", or "NotApplicable".
  2. Fix casing in the source JSON: {"name":"https"} → {"Name":"https"}.
  3. Before deserializing untrusted data, check the variant tag: parse to serde_json::Value and verify the key is one of the allowed set, mapping legacy/renamed tags explicitly.
  4. If a genuinely new variant is needed, extend the enum and the match arms in service.rs (and its Serialize impl) together, then regenerate the data files.

Example fix

// before — unknown/misspelled variant tag
let e = serde_json::from_str::<Service>("{\"name\":\"https\"}");
// Err: unknown variant `name`, expected one of `Name`, `Unknown`, `NotApplicable`

// after — normalize the tag before parsing
let v: serde_json::Value = serde_json::from_str(raw)?;
if let Some(tag) = v.as_object().and_then(|m| m.keys().next()) {
    assert!(matches!(tag.as_str(), "Name" | "Unknown" | "NotApplicable"), "bad tag {tag}");
}
let s: Service = serde_json::from_value(v)?; // {"Name":"https"} → Service::Name("https")
Defensive patterns

Strategy: type-guard

Validate before calling

// allow-list the variant tag before deserializing
const SERVICE_VARIANTS: [&str; 3] = ["Name", "Unknown", "NotApplicable"];
fn variant_tag_ok(v: &serde_json::Value) -> bool {
    match v {
        serde_json::Value::String(s) => SERVICE_VARIANTS.contains(&s.as_str()),
        serde_json::Value::Object(m) => m.len() == 1
            && SERVICE_VARIANTS.contains(&m.keys().next().map(String::as_str).unwrap_or_default()),
        _ => false,
    }
}

Type guard

fn is_known_service_variant(tag: &str) -> bool {
    matches!(tag, "Name" | "Unknown" | "NotApplicable")
}

Try / catch

// distinguish unknown-variant from other serde errors and recover with a default
match serde_json::from_str::<Service>(raw) {
    Ok(s) => s,
    Err(e) if e.is_data() && e.to_string().starts_with("unknown variant") => {
        Service::Unknown // or log & reject: variant names are case-sensitive, fix the producer
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: serde_json::from_str::<Service> on input whose enum tag is misspelled or new: `{"name":"https"}` (lowercase), `{"NAME":"https"}`, `{"Known":"https"}`, or a future/removed variant like `{"Port":443}`. Any string tag outside the three accepted names reaches the `other` arm and produces this error; the unit tests in service.rs (test_deserialize_invalid_variant) exercise exactly this path.

Common situations: Case mismatches from hand-written JSON or non-Rust producers (JavaScript camelCase); schema drift between a producer serialization of a different enum version and Sniffnet's fixed variant list; renaming variants in a fork without updating data files; pipelines writing the display name of the service ('HTTPS') instead of the variant tag.

Related errors


AI-assisted analysis of GyulyVGC/sniffnet@48b0575dc0 (2026-08-16). Data as JSON: /api/errors/2e921f93c8749c39. Report an issue: GitHub.