Skip to content

fix: keep OpenTelemetry running when resource detection is incomplete - #2

Merged
Timo972 merged 1 commit into
mainfrom
fix/otel-resource-detection-nonfatal
Aug 10, 2026
Merged

fix: keep OpenTelemetry running when resource detection is incomplete#2
Timo972 merged 1 commit into
mainfrom
fix/otel-resource-detection-nonfatal

Conversation

@Timo972

@Timo972 Timo972 commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Root cause

The runtime image runs as USER 65532:65532, but debian:bookworm-slim has no account at that UID:

$ docker run --rm --user 65532:65532 debian:bookworm-slim getent passwd 65532
NO PASSWD ENTRY FOR 65532

So OTel's processOwnerDetector calls user.Current(), which fails, resource.New returns that error, and Init treated it as fatal — disabling telemetry in every container.

Why the obvious guard would not have worked

The SDK's own documented pattern is errors.Is(err, resource.ErrPartialResource). That does not catch this case — processOwnerDetector.Detect returns user.Current()'s error verbatim, unwrapped:

func (processOwnerDetector) Detect(context.Context) (*Resource, error) {
	owner, err := owner()
	if err != nil {
		return nil, err   // not wrapped in ErrPartialResource
	}
	...
}

detect() joins the error but still merges every other detector, so the resource keeps env, PID, executable, command args, runtime, host and service.name — only process.owner is missing. An incomplete resource is a degraded one, not an invalid one.

Changes

  • internal/telemetry/otel.go — log detection failures as a warning and continue with the resource, instead of aborting startup.
  • Dockerfile — create the nonroot account the numeric USER refers to, so the lookup actually succeeds and process.owner is populated rather than merely tolerated. USER stays numeric so Kubernetes runAsNonRoot can verify it.

Verification

End-to-end, real binary under --user 65532:65532 with OTEL_EXPORTER_OTLP_ENDPOINT set:

build result
pre-fix application stopped with an error: initialize telemetry failed
post-fix, no passwd entry WARN incomplete telemetry resourceINFO telemetry initialized → startup continues
post-fix, with passwd entry INFO telemetry initialized, no warning — owner resolves

Confirmed the image change works with CGO_ENABLED=0 (pure-Go os/user reads /etc/passwd), which is how this binary ships.

Added TestInitKeepsPartialResourceWhenDetectionFails, written first and watched fail with the exact production error before the fix. go vet ./..., go test -race ./..., go build ./cmd/app, and gofmt are all clean.

🤖 Generated with Claude Code

The runtime image sets USER 65532:65532 but never creates a matching
account, so the process owner detector's user.Current call fails and
resource.New returns an error. Init treated that as fatal, which
disabled OpenTelemetry entirely in every container.

resource.New still returns the attributes its other detectors produced,
so an incomplete resource is a degraded one, not an invalid one. Log the
detection failure and carry on. Checking errors.Is(err,
resource.ErrPartialResource) would not have helped here: the process
owner detector returns user.Current's error verbatim, unwrapped.

Also create the nonroot account the numeric USER refers to, so the
lookup succeeds and process.owner is populated instead of merely
tolerated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Timo972
Timo972 merged commit 58d4d51 into main Aug 10, 2026
8 checks passed
@Timo972
Timo972 deleted the fix/otel-resource-detection-nonfatal branch August 10, 2026 10:04
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.

1 participant