Skip to content

prometheus: don't panic when wrapping an invalid Desc with a prefix - #2159

Open
mrueg wants to merge 1 commit into
prometheus:mainfrom
mrueg:prometheus-wrap-invalid-desc
Open

mrueg wants to merge 1 commit into
prometheus:mainfrom
mrueg:prometheus-wrap-invalid-desc

Conversation

@mrueg

@mrueg mrueg commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Summary

wrapDesc passed every Desc through V2.NewDesc, even one that already carried an error. A Desc created by NewInvalidDesc has a nil variableLabels. Without a prefix, the empty name fails validation early, but with a non-empty prefix the name is valid and NewDesc dereferences the nil variableLabels.

As a result, a collector registered via WrapRegistererWithPrefix that signals failure with one of the documented patterns crashes:

  • Describe sending NewInvalidDesc(err): Register panics inside the Describe goroutine, which cannot be recovered, so the process crashes.
  • Collect sending NewInvalidMetric(NewInvalidDesc(err), err) from an unchecked collector: Gather panics instead of returning err.

This change returns the error of an invalid Desc directly instead of building a new Desc from it. The earlier precedence rule ("earlier errors get precedence") is unchanged.

This also matters for #2029, which recovers panics in wrapped collectors by sending NewInvalidDesc / NewInvalidMetric(NewInvalidDesc(err), err) through the wrapper, i.e. exactly the input that crashes here when a prefix is used.

Testing

Added the table-driven TestWrapInvalidDesc, covering labels, prefix, and both, for Register and Gather. It crashes with a nil pointer dereference before the fix and passes after it. go test -race ./prometheus/... passes.

🤖 Generated with Claude Code

wrapDesc passed the Desc through V2.NewDesc even if it carried an error.
A Desc created by NewInvalidDesc has a nil variableLabels, and with a
non-empty prefix the name passes validation, so NewDesc dereferenced it.

As a result, a collector signalling failure with NewInvalidDesc or
NewInvalidMetric(NewInvalidDesc(err), err), both documented patterns,
crashed the process in Register (inside the Describe goroutine, so it
cannot be recovered) or panicked in Gather when registered via
WrapRegistererWithPrefix.

Return the error of an invalid Desc directly instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Manuel Rüger <manuel@rueg.eu>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The localized fix preserves valid-descriptor behavior and adds regression coverage for both reported failure paths.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes invalid-descriptor handling in Prometheus collector wrappers so prefixed wrappers return errors instead of panicking.

Changes:

  • Propagates existing descriptor errors without rebuilding invalid descriptors.
  • Adds regression tests for registration and gathering with labels, prefixes, and both.
File Description
prometheus/​wrap.go Handles invalid descriptors before constructor validation.
prometheus/​wrap_test.go Tests error propagation through wrapped registration and gathering.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants