Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
* [BUGFIX] Distributor: Return HTTP 499 (Client Closed Request) instead of 500 when a remote-write or OTLP push is canceled by the client, so client-side cancellations are no longer counted as server-side errors. #7717
* [BUGFIX] Querier: Fix gRPC `codes.Canceled` errors being mapped to HTTP 500 instead of 499 when a client cancels a query. #7738
* [BUGFIX] Compactor: Fix spurious `bucket operation fail after retries` error logs emitted during partial block cleanup. #7749
* [BUGFIX] Alertmanager: Fix panic in `validateAlertmanagerConfig` when receiver config traversal encounters nil interface values. #7751

## 1.21.1 2026-06-04

Expand Down
2 changes: 1 addition & 1 deletion pkg/alertmanager/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,12 @@ var configValidators = map[reflect.Type]func(any) error{
// first error or nil if validation succeeds.
func validateAlertmanagerConfig(cfg any) error {
v := reflect.ValueOf(cfg)
t := v.Type()

// Skip invalid, the zero value or a nil pointer (checked by zero value).
if !v.IsValid() || v.IsZero() {
return nil
}
t := v.Type()

// If the input config is a pointer then we need to get its value.
// At this point the pointer value can't be nil.
Expand Down
36 changes: 36 additions & 0 deletions pkg/alertmanager/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1367,3 +1367,39 @@ func TestValidateAlertmanagerConfig(t *testing.T) {
})
}
}

func TestValidateAlertmanagerConfig_DoesNotPanicOnNilInterfaceValues(t *testing.T) {
tests := map[string]any{
"nil root interface": any(nil),
"map value nil interface": map[string]any{"test": nil},
"slice value nil interface": []any{nil},
}

for testName, input := range tests {
t.Run(testName, func(t *testing.T) {
require.NotPanics(t, func() {
err := validateAlertmanagerConfig(input)
assert.NoError(t, err)
})
})
}
}

func TestValidateAlertmanagerConfig_PagerdutyDetailsNullValue(t *testing.T) {
amCfg, err := config.Load(`
route:
receiver: pd
receivers:
- name: pd
pagerduty_configs:
- routing_key: "abc123"
details:
foo: null
`)
require.NoError(t, err)

require.NotPanics(t, func() {
err = validateAlertmanagerConfig(amCfg)
})
assert.NoError(t, err)
}