vectordotdev/vector · error

unit structs should be rejected during AST parsing

Error message

unit structs should be rejected during AST parsing

What it means

Same panic family as errorIndex 8 but on the rate-metric branch of `decode_ddseries_v2` (src/sources/datadog_agent/metrics.rs:345): `Utc.timestamp_opt(dd_point.timestamp, 0).single().expect("invalid timestamp")` panics when the Datadog point's seconds-since-epoch timestamp is outside chrono's supported range. It affects rate/count-type points (branch with `.with_interval_ms(non_rate_interval)`).

Solutions

  1. Validate `dd_point.timestamp` against a sane epoch-seconds range before building the metric and drop the point with a warning on failure.
  2. Use `.single()` result directly (Option) and skip the point instead of expect, mirroring the non-rate branch fix.
  3. Convert milliseconds to seconds (`ts / 1000`) if the upstream emitter documents ms units.

Example fix

// before
.with_timestamp(Some(
    Utc.timestamp_opt(dd_point.timestamp, 0)
        .single()
        .expect("invalid timestamp"),
))
// after
let ts = Utc.timestamp_opt(dd_point.timestamp, 0).single()?;
// ... .with_timestamp(Some(ts))
Defensive patterns

Strategy: validation

Validate before calling

fn valid_dd_timestamp(secs: i64) -> bool {
    (0..=253_402_300_799).contains(&secs)
}

Type guard

fn dd_ts_to_utc(secs: i64) -> Option<DateTime<Utc>> {
    if !(0..=253_402_300_799).contains(&secs) { return None; }
    Utc.timestamp_opt(secs, 0).single()
}

Try / catch

// In the rate branch, propagate None upward:
let ts = Utc.timestamp_opt(dd_point.timestamp, 0).single()?;
// builder.with_timestamp(Some(ts))

Prevention

When it happens

Trigger: A v2 series payload with a rate/count point whose `timestamp` i64 cannot be represented as a UTC datetime — epoch-milliseconds supplied where seconds are expected, negative values, or i64-near-max garbage from a malformed/protobuf-unmarshal-adjacent issue.

Common situations: Third-party emitters masquerading as the Datadog agent sending wrong timestamp units; corrupted or truncated protobuf payloads; test fixtures with placeholder timestamps like 0 or i64::MAX.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/4b6c14f3d8a06a21. Report an issue: GitHub.

Appendix: source

Thrown at lib/vector-config-macros/src/configurable.rs:220

            variants
                .iter()
                .filter(|variant| variant.tagging() == &Tagging::None)
                .count()
                >= 2
        }
    }
}

fn build_struct_generate_schema_fn(
    container: &Container<'_>,
    style: &Style,
    fields: &[Field<'_>],
) -> proc_macro2::TokenStream {
    match style {
        Style::Struct => build_named_struct_generate_schema_fn(container, fields),
        Style::Tuple => build_tuple_struct_generate_schema_fn(fields),
        Style::Newtype => build_newtype_struct_generate_schema_fn(fields),
        Style::Unit => panic!("unit structs should be rejected during AST parsing"),
    }
}

fn generate_struct_field(field: &Field<'_>, sibling_keys: &[String]) -> proc_macro2::TokenStream {
    let field_metadata_ref = Ident::new("field_metadata", Span::call_site());
    let field_metadata = generate_field_metadata(&field_metadata_ref, field);
    let field_schema_ty = get_field_schema_ty(field);

    // Flattened `Option<T>` cannot use `Option`'s nullable-property schema: `allOf` merge
    // validates the parent object, which is never JSON `null`. Tagged enums get an absence
    // encoding instead; other `Option<T>` flatten fields fall back to the property schema.
    let spanned_generate_schema = match (field.flatten(), option_inner_type(field_schema_ty)) {
        (true, Some(inner_ty)) => {
            let sibling_key_lits = sibling_keys.iter().map(|key| quote! { #key });
            quote_spanned! {field.span()=>
                ::vector_config::schema::generate_flattened_optional_schema(
                    &<#inner_ty as ::vector_config::Configurable>::as_configurable_ref(),
                    &<#field_schema_ty as ::vector_config::Configurable>::as_configurable_ref(),

View on GitHub (pinned to bdb87aeaa4)