[bug-hunter] Beats receiver startup panics when NewForReceiver is called with nil Metrics
- Dominant language
- Go
- Stars
- 12.7k
- Forks
- 5k
- Avg merge
- 2d 15m
- Merged PRs (30d)
- 385
Description
## Impact
`pipeline.NewForReceiver` crashes the process when `Monitors.Metrics` is nil, instead of handling it like `pipeline.New` (which keeps a nil observer when metrics are absent). This is user-impacting for receiver startup paths that do not wire a metrics registry: startup becomes a hard panic (`SIGSEGV`) rather than a recoverable error path.
## Reproduction Steps
1. From repo root, create this reproduction file at `/tmp/gh-aw/agent/repro_nil_metrics.go`:
```go
package main
import (
"github.com/elastic/beats/v7/libbeat/beat"
"github.com/elastic/beats/v7/libbeat/publisher/pipeline"
"github.com/elastic/elastic-agent-libs/config"
)
func main() {
_, _ = pipeline.NewForReceiver(
beat.Info{Name: "repro"},
pipeline.Monitors{Metrics: nil},
config.Namespace{},
pipeline.Settings{},
"",
)
}
```
2. Run:
```bash
cd /home/runner/work/beats/beats
go run /tmp/gh-aw/agent/repro_nil_metrics.go
```
## Expected vs Actual
**Expected:** `NewForReceiver` should handle nil metrics safely (matching `pipeline.New` behavior) and not panic.
**Actual:** process crashes with nil-pointer panic:
```text
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xbf9e23]
goroutine 1 [running]:
github.com/elastic/elastic-agent-libs/monitoring.(*Registry).getOrCreateRegistry(0x0, {0xc000240390, 0x1, 0x1}, {0x0, 0x0, 0x0})
/home/runner/go/pkg/mod/github.com/elastic/elastic-agent-libs@v0.33.3/monitoring/registry.go:157 +0x83
github.com/elastic/elastic-agent-libs/monitoring.(*Registry).GetOrCreateRegistry(0x0, {0x1220f61?, 0x8b139d?}, {0x0, 0x0, 0x0})
/home/runner/go/pkg/mod/github.com/elastic/elastic-agent-libs@v0.33.3/monitoring/registry.go:149 +0x6a
github.com/elastic/beats/v7/libbeat/publisher/pipeline.newMetricsObserver(0x0)
/home/runner/work/beats/beats/libbeat/publisher/pipeline/monitoring.go:81 +0x32
github.com/elastic/beats/v7/libbeat/publisher/pipeline.NewForReceiver(...)
/home/runner/work/beats/beats/libbeat/publisher/pipeline/pipeline.go:207 +0x8a
main.main()
/tmp/gh-aw/agent/repro_nil_metrics.go:10 +0x6d
exit status 2
```
## Failing Test
Minimal reproduction script above is sufficient as a failing test case (deterministic panic).
## Evidence
- `libbeat/publisher/pipeline/pipeline.go:207` initializes observer unconditionally:
- `observer: newMetricsObserver(monitors.Metrics),`
- `libbeat/publisher/pipeline/monitoring.go:81` dereferences `metrics`:
- `reg := metrics.GetOrCreateRegistry("pipeline")`
- `libbeat/publisher/pipeline/pipeline.go:171-173` (`New`) already has nil guard:
- `if monitors.Metrics != nil { p.observer = newMetricsObserver(monitors.Metrics) }`
- `git blame` shows `NewForReceiver` line introduced in `c073ffbc1afcbdef42b0edc315deda03e9259582` (`Add otel-specific outputController to libbeat pipeline (#50075)`).
> [!NOTE]
>
> 🔒 Integrity filter blocked 10 items
>
> The following items were blocked because they don't meet the GitHub integrity level.
>
> - [#50075](https://github.com/elastic/beats/pull/50075) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#50100](https://github.com/elastic/beats/issues/50100) `search_issues`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#50143](https://github.com/elastic/beats/pull/50143) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#49415](https://github.com/elastic/beats/pull/49415) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#42036](https://github.com/elastic/beats/pull/42036) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#39405](https://github.com/elastic/beats/pull/39405) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#40686](https://github.com/elastic/beats/pull/40686) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#37437](https://github.com/elastic/beats/pull/37437) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#29225](https://github.com/elastic/beats/pull/29225) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#27620](https://github.com/elastic/beats/pull/27620) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
>
> To allow these resources, lower `min-integrity` in your GitHub frontmatter:
>
> ```yaml
> tools:
> github:
> min-integrity: approved # merged | approved | unapproved | none
> ```
>
>
---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/beats/actions/runs/24562441298)
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on Apr 24, 2026, 11:34 AM UTC
Contributor guide
Research direction
Start in libbeat/publisher/pipeline/pipeline.go, comparing NewForReceiver around line 207 with New around lines 171-173, then inspect newMetricsObserver in monitoring.go. Run the provided Go reproduction and add focused regression coverage for a nil Metrics monitor. Done means NewForReceiver no longer panics and the test passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100