Skip to content

fix(MonitorThresholds): treat empty string as null for f64 threshold fields#1292

Open
platinummonkey wants to merge 1 commit intoDataDog:masterfrom
platinummonkey:fix/monitor-thresholds-empty-string-deserialize
Open

fix(MonitorThresholds): treat empty string as null for f64 threshold fields#1292
platinummonkey wants to merge 1 commit intoDataDog:masterfrom
platinummonkey:fix/monitor-thresholds-empty-string-deserialize

Conversation

@platinummonkey
Copy link

Summary

The Datadog API occasionally returns "" (empty string) instead of null for unset threshold values on certain monitor types (e.g. service check monitors, composite monitors with partial threshold configs). The MonitorThresholds deserializer only guarded critical against null, leaving empty strings to fall through to serde_json::from_value::<f64>() which panics with:

Serde(Error("invalid type: string \"\", expected f64", line: 1, column: ...))

This causes list_monitors to fail entirely for any org that has one of these monitors.

Changes

  • src/datadogV1/model/model_monitor_thresholds.rs: Add || v.as_str() == Some("") guard to all six threshold fields: critical, critical_recovery, ok, unknown, warning, warning_recovery

Reproducer

Call list_monitors on an org that has service-check monitors or composite monitors where optional thresholds (warning, critical_recovery, etc.) were never set via the API — the UI sometimes persists these as "" rather than omitting the field.

Test

The existing MonitorThresholds deserialization tests should continue to pass. A new case worth adding:

let json = r#"{"critical": "", "warning": "", "critical_recovery": null}"#;
let t: MonitorThresholds = serde_json::from_str(json).unwrap();
assert!(t.critical.is_none());
assert!(t.warning.is_none());

…fields

The Datadog API returns "" instead of null for unset threshold values on
some monitor types (e.g. service check monitors, composite monitors).
The deserializer only guarded against null, causing a serde panic:
  invalid type: string "", expected f64

Apply the same null-skip guard to all six threshold fields:
critical, critical_recovery, ok, unknown, warning, warning_recovery.

Reproducer: call ListMonitors on an org that has service-check monitors
with unset warning/critical_recovery thresholds.
@platinummonkey platinummonkey requested review from a team as code owners March 1, 2026 01:05
platinummonkey added a commit to datadog-labs/pup that referenced this pull request Mar 1, 2026
Implements `pup vet` per the design in discussion #132. Surfaces
universally broken Datadog configurations with a single monitors
API call.

Checks implemented:
- silent-monitors (CRITICAL): monitors with no @-mention/notification
  channel in their message — alerts fire into the void
- stale-monitors (WARNING): monitors currently in "No Data" state —
  abandoned or misconfigured data source
- muted-forgotten (WARNING): monitors muted indefinitely or with a
  silence expiry >30 days out

New files:
- src/ops/mod.rs + src/ops/vet.rs — check engine with shared types
  (Severity, Resource, Finding, VetResult)
- src/commands/vet.rs — CLI presentation layer (human + agent mode)

Usage:
  pup vet                          # run all checks
  pup vet --tags=team:platform     # scope by monitor tags
  pup vet --check=silent-monitors  # single check
  pup vet --severity=critical      # filter output
  pup vet list                     # list available checks

Also adds a [patch.crates-io] for datadog-api-client pointing at a
local fix branch for a serde deserialisation crash when the Datadog
API returns "" for f64 threshold fields (MonitorThresholds). Upstream
fix proposed at DataDog/datadog-api-client-rust#1292.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
match k.as_str() {
"critical" => {
if v.is_null() {
if v.is_null() || v.as_str() == Some("") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is generated so it would be replaced on the next spec change. You'd likely have to make the change to

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants