elastic / elastic/beats

[bug-hunter] BeatReceiver.Start panics on Run error when beater lacks OTEL wrapper

Open
#49,517 4 comments 0 reactions 0 assignees View on GitHub
needs_team
Dominant language
Go
Stars
12.7k
Forks
5k
Avg merge
2d 15m
Merged PRs (30d)
385

Description

## Impact
A receiver startup failure can crash with a panic instead of returning an error. This turns a recoverable startup error into process termination for beat receivers that do not implement `cfgfile.WithOtelFactoryWrapper`.

## Reproduction Steps
1. Create this new test file at `x-pack/libbeat/cmd/instance/repro_receiver_panic_test.go`:

```go
package instance

import (
"errors"
"testing"

"github.com/elastic/beats/v7/libbeat/beat"
beatinstance "github.com/elastic/beats/v7/libbeat/cmd/instance"
"github.com/elastic/beats/v7/libbeat/management"
"github.com/elastic/elastic-agent-libs/config"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componentstatus"
)

type failingBeater struct{}

func (f *failingBeater) Run(*beat.Beat) error { return errors.New("boom") }
func (f *failingBeater) Stop() {}

type emptyHost struct{}

func (h *emptyHost) GetExtensions() map[component.ID]component.Component { return nil }
func (h *emptyHost) Report(*componentstatus.Event) {}

// Expected behavior: Start should return an error when Run fails.
// Actual behavior: Start panics because groupReporter is nil.
func TestReproStartShouldReturnErrorInsteadOfPanic(t *testing.T) {
disableMetricsLog, err := config.NewConfigFrom(map[string]interface{}{"enabled": false})
if err != nil {
t.Fatalf("config setup failed: %v", err)
}

b := &beatinstance.Beat{}
b.Manager = &management.FallbackManager{}
b.Config.MetricLogging = disableMetricsLog

br := &BeatReceiver{beat: b, beater: &failingBeater{}}

if err := br.Start(&emptyHost{}); err == nil {
t.Fatal("expected run error, got nil")
}
}
```

2. Run:

```bash
go test ./x-pack/libbeat/cmd/instance -run TestReproStartShouldReturnErrorInsteadOfPanic -count=1
```

## Expected vs Actual
**Expected:** `BeatReceiver.Start` returns `beat receiver run error: boom` (or equivalent wrapped error).

**Actual:** panic due to nil dereference:

```text
--- FAIL: TestReproStartShouldReturnErrorInsteadOfPanic (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
...
github.com/elastic/beats/v7/x-pack/libbeat/cmd/instance.(*BeatReceiver).Start(...)
/home/runner/work/beats/beats/x-pack/libbeat/cmd/instance/receiver.go:187 +0x5ef
...
FAIL github.com/elastic/beats/v7/x-pack/libbeat/cmd/instance 0.022s
```

## Failing Test
The full failing test is included in Reproduction Step 1.

## Evidence
- `x-pack/libbeat/cmd/instance/receiver.go:119-122` initializes `groupReporter` only if `br.beater` implements `cfgfile.WithOtelFactoryWrapper`.
- `x-pack/libbeat/cmd/instance/receiver.go:185-188` unconditionally calls `groupReporter.UpdateStatus(...)` on run error.
- `git blame` shows line 187 (`groupReporter.UpdateStatus`) was added in commit `2ac081b1086`, making the nil call reachable when `Run` returns an error and wrapper is not implemented.

---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/beats/actions/runs/23191576728)

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on Mar 24, 2026, 12:12 PM UTC

Contributor guide

Open the contributing guide

Research direction

Start with x-pack/libbeat/cmd/instance/receiver.go, especially the groupReporter initialization at lines 119-122 and the run-error path at lines 185-188. Add the regression test from the issue as x-pack/libbeat/cmd/instance/repro_receiver_panic_test.go, then run go test ./x-pack/libbeat/cmd/instance -run TestReproStartShouldReturnErrorInsteadOfPanic -count=1. Done means Start returns the run error instead of panicking when the beater lacks the OTEL wrapper.

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
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.