fix(llma): tolerate null numeric values in OTLP JSON ingestion - #54414
Merged
richardsolomou merged 2 commits intoApr 14, 2026
Conversation
The Vercel AI SDK (and potentially other OTLP exporters) emits span
attributes with null scalar values like {"doubleValue": null} for
metrics that aren't yet available on partial stream chunks. The
opentelemetry-proto Rust types define doubleValue as f64 (non-optional),
so serde rejects the null during deserialization.
Extend patch_otel_json to strip null-valued OTLP scalar fields
(doubleValue, intValue, stringValue, boolValue, bytesValue) from
AnyValue objects. In protobuf-JSON encoding a missing key is equivalent
to an unset scalar, so removal is semantically correct.
Generated-By: PostHog Code
Task-Id: 156a00d2-1b8f-42e0-8dbf-0ee20ae1167c
Contributor
Prompt To Fix All With AIThis is a comment left during a code review.
Path: rust/capture/src/otel/ingestion.rs
Line: 258-277
Comment:
**Prefer parameterised test for null scalar types**
The test hard-codes `doubleValue` and `intValue` but leaves `stringValue`, `boolValue`, and `bytesValue` untested for the null case. Per the project's preference for parameterised tests, and to give a clear failure message per variant, consider iterating over all five scalar types:
```rust
#[test]
fn test_patch_otel_json_null_scalar_attrs() {
for field in &["doubleValue", "intValue", "stringValue", "boolValue", "bytesValue"] {
let mut v = serde_json::json!({"value": {}});
v["value"].as_object_mut().unwrap().insert(field.to_string(), Value::Null);
patch_otel_json(&mut v);
assert_eq!(v["value"], Value::Null, "field `{field}` with null should be stripped");
}
// non-null scalar must be preserved
let mut v = serde_json::json!({"value": {"stringValue": "gpt-4"}});
patch_otel_json(&mut v);
assert_eq!(v["value"]["stringValue"], "gpt-4");
}
```
This also guards against future regressions if a new scalar type is added to the stripping list.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(llma): tolerate null numeric values ..." | Re-trigger Greptile |
Generated-By: PostHog Code Task-Id: 156a00d2-1b8f-42e0-8dbf-0ee20ae1167c
andrewm4894
approved these changes
Apr 14, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
PostHog's OTEL ingestion endpoint (
/i/v0/ai/otel) returns 400 when receiving OTLP/JSON payloads containing null-valued scalar attributes like{"doubleValue": null}. The Vercel AI SDK emits these for cost/token metrics on partial stream chunks. Theopentelemetry-protocrate typesdoubleValueasf64(non-optional), soserde_json::from_valuerejects the null with:Changes
Extends
patch_otel_jsoninrust/capture/src/otel/ingestion.rsto strip null-valued OTLP scalar fields (doubleValue,intValue,stringValue,boolValue,bytesValue) from AnyValue objects before deserialization. In protobuf-JSON encoding, a missing key is equivalent to an unset scalar, so removal is semantically correct — no coercion to default values.The existing
{} → nullpatching (for opentelemetry-rust#1253) is preserved as a special case of the same logic.How did you test this code?
I am an agent and have not tested this manually. Automated testing:
test_patch_otel_json_null_scalar_attrs: verifies{"doubleValue": null}and{"intValue": null}are stripped toValue::Nullwhile{"stringValue": "gpt-4"}is preservedtest_parse_json_with_null_double_attr: verifies the full pipeline (JSON parse → patch → deserialize intoExportTraceServiceRequest) succeeds with a nulldoubleValueattributePublish to changelog?
no
Docs update
N/A
🤖 LLM context
Agent-authored PR. Single-file change to
rust/capture/src/otel/ingestion.rs— extends the existing JSON patching helper to handle a second class of OTLP/Rust type mismatch (null scalars in addition to empty objects).Created with PostHog Code