{"record":{"id":"60daf8d2a58326d6","repo":"vectordotdev/vector","slug":"error-tps-cannot-be-nan","errorCode":null,"errorMessage":"error_tps cannot be Nan","messagePattern":"error_tps cannot be Nan","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/datadog_agent/traces.rs","lineNumber":154,"sourceCode":"                trace_event\n                    .metadata_mut()\n                    .set_datadog_api_key(Arc::clone(k));\n            }\n            trace_event.insert(\n                &source.log_schema_source_type_key,\n                Bytes::from(\"datadog_agent\"),\n            );\n            trace_event.insert(event_path!(\"payload_version\"), \"v2\".to_string());\n            trace_event.insert(&source.log_schema_host_key, hostname.clone());\n            trace_event.insert(event_path!(\"env\"), env.clone());\n            trace_event.insert(event_path!(\"agent_version\"), agent_version.clone());\n            trace_event.insert(\n                event_path!(\"target_tps\"),\n                Value::Float(NotNan::new(target_tps).expect(\"target_tps cannot be Nan\")),\n            );\n            trace_event.insert(\n                event_path!(\"error_tps\"),\n                Value::Float(NotNan::new(error_tps).expect(\"error_tps cannot be Nan\")),\n            );\n            if let Some(Value::Object(span_tags)) = trace_event.get_mut(event_path!(\"tags\")) {\n                span_tags.extend(tags.clone());\n            } else {\n                trace_event.insert(event_path!(\"tags\"), Value::from(tags.clone()));\n            }\n            Event::Trace(trace_event)\n        })\n        .collect();\n    Ok(enriched_events)\n}\n\nfn convert_dd_tracer_payload(payload: ddtrace_proto::TracerPayload) -> Vec<TraceEvent> {\n    let tags = convert_tags(payload.tags);\n    payload\n        .chunks\n        .into_iter()\n        .map(|trace| {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/src/sources/datadog_agent/traces.rs#L136-L172","documentation":"Same invariant as target_tps but for the error_tps double of the ddtrace v2 protobuf payload: Value::Float(NotNan::new(error_tps).expect(\"error_tps cannot be Nan\")). NotNan::new fails only for NaN, and protobuf doubles can encode NaN, so a payload with that bit pattern panics the trace-decoding task.","triggerScenarios":"A TracePayload protobuf POSTed to the datadog_agent traces endpoint whose error_tps field is NaN - corrupt frames, hostile payloads, or custom senders writing uninitialized floats.","commonSituations":"Fuzzed or replayed trace payloads, interop with non-compliant tracers, corrupted bodies in transit. The panic loses the whole batch of trace events in that request.","solutions":["Guard before inserting: if let Some(tps) = NotNan::new(error_tps) and log-and-skip on Err","Validate float fields immediately after TracePayload::decode and reject the request with 422 instead of panicking","Upgrade Vector once a fix lands"],"exampleFix":"// before\ntrace_event.insert(\n    event_path!(\"error_tps\"),\n    Value::Float(NotNan::new(error_tps).expect(\"error_tps cannot be Nan\")),\n);\n\n// after\nif let Some(tps) = NotNan::new(error_tps) {\n    trace_event.insert(event_path!(\"error_tps\"), Value::Float(tps));\n} else {\n    warn!(message = \"dropping NaN error_tps from datadog agent payload\");\n}","handlingStrategy":"validation","validationCode":"fn finite_or_zero(v: f64) -> f64 {\n    if v.is_finite() { v } else { 0.0 }\n}\n\n// before insert:\nif !error_tps.is_finite() {\n    warn!(value = error_tps, \"non-finite error_tps from agent payload\");\n    error_tps = 0.0;\n}","typeGuard":"fn as_not_nan(v: f64) -> Option<ordered_float::NotNan<f64>> {\n    ordered_float::NotNan::new(v).ok()\n}","tryCatchPattern":"if let Some(tps) = NotNan::new(error_tps) {\n    trace_event.insert(event_path!(\"error_tps\"), Value::Float(tps));\n} else {\n    warn!(message = \"dropping NaN error_tps\");\n}","preventionTips":["Apply the same is_finite() validation to every numeric field copied out of the ddtrace payload","Fail the request early (422) when any double field is non-finite","Fuzz protobuf doubles with NaN bit patterns in CI"],"tags":["rust","panic","nan","ordered-float","datadog-agent","traces","protobuf"],"backgroundTag":"nan-in-numeric-field","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}