Skip to content

Fix NPE when Spring messaging handler is invoked with a null message (quick fix) - #12690

Open
dougqh wants to merge 1 commit into
masterfrom
dougqh/spring-messaging-null-message
Open

dougqh wants to merge 1 commit into
masterfrom
dougqh/spring-messaging-null-message

Conversation

@dougqh

@dougqh dougqh commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

Fixes a NullPointerException in the Spring messaging instrumentation when a handler is invoked with a null message.

  • SpringMessageHandlerInstrumentation.ContextPropagationAdvice now skips context extraction when the Message argument is null (message != null && activeSpan() == null), so no extract/attach work is done for it.
  • SpringMessageExtractAdapter.forEachKey now returns early for a null carrier instead of dereferencing it.
  • Adds SpringMessageExtractAdapterTest (JUnit 5): null message, message without headers, and key normalization / non-string headers. The null-message case fails without the fix.

Motivation

Instrumentation telemetry shows this NPE at SpringMessageExtractAdapter.forEachKey:37 (carrier.getHeaders()), reported as "Failed to handle exception in instrumentation for org.springframework.messaging.handler.invocation.InvocableHandlerMethod - SpringMessageHandlerInstrumentation$ContextPropagationAdvice". It is steady at about 2-2.8k events an hour (~46k a day), from many services on 1.65 and 1.66 (mostly one customer's EV backend services, plus a futures-markets service). Each report aggregates repeats (one sample had count: 1673), so the real number of exceptions thrown is higher.

There is nothing to extract from a null message, so no tracing data is lost. The cost is an exception thrown and reported on every such invocation.

Additional Notes

  • History: the unguarded dereference of the carrier dates from the adapter's original version (2023); Avoid NPE when inspecting spring messaging headers #10254 (Dec 2025) guarded a null getHeaders() result but not a null carrier. The failure became its own reported advice when Split tracing and context tracking in server and messaging integrations #10767 (v1.61.0) split out ContextPropagationAdvice. I could not tell from telemetry which Spring code path passes a null message.
  • The exit advice already null-checks the scope (if (scope != null) scope.close()), so a skipped extraction is safe.
  • The two null checks are intentional: the advice guard avoids the work, and the adapter guard keeps the getter safe for any other caller. Happy to drop the adapter one if reviewers prefer the fix in one place.
  • No test covers the advice path itself (null message with no active span); advice classes are awkward to unit test.

Contributor Checklist

Jira ticket: N/A

🤖 Generated with Claude Code

ContextPropagationAdvice extracted context from the handler's message
argument without a null check, and SpringMessageExtractAdapter dereferenced
its carrier unguarded, so a null message threw an NPE on every invocation
that had no active span. Skip extraction when the message is null and make
the adapter tolerate a null carrier.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@dougqh dougqh added type: bug fix Bug fix tag: no release notes Changes to exclude from release notes inst: spring Spring instrumentation tag: ai generated Largely based on code generated by an AI or LLM labels Sep 29, 2026
@dougqh dougqh changed the title Fix NPE when Spring messaging handler is invoked with a null message Fix NPE when Spring messaging handler is invoked with a null message (quick fix) Sep 29, 2026
@dougqh
dougqh marked this pull request as ready for review September 29, 2026 19:17
@dougqh
dougqh requested a review from a team as a code owner September 29, 2026 19:17
@dougqh
dougqh requested review from jordan-wong and removed request for a team September 29, 2026 19:17

@datadog-prod-us1-6 datadog-prod-us1-6 Bot 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.

Bits Code Review: PASS

More details

Both the advice-level and adapter-level guards make null messages a safe no-op while preserving context extraction for non-null messages.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit d5e91fe · @DataDog review to ask questions

@datadog-prod-us1-6

Copy link
Copy Markdown

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 68.82% (+9.58%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: d5e91fe | Docs | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.10 s 14.08 s [-0.7%; +1.0%] (no difference)
startup:insecure-bank:tracing:Agent 13.02 s 13.09 s [-1.3%; +0.2%] (no difference)
startup:petclinic:appsec:Agent 16.91 s 16.89 s [-1.0%; +1.2%] (no difference)
startup:petclinic:iast:Agent 16.96 s 17.04 s [-1.4%; +0.5%] (no difference)
startup:petclinic:profiling:Agent 16.51 s 16.18 s [-2.6%; +6.7%] (no difference)
startup:petclinic:sca:Agent 16.85 s 16.69 s [+0.0%; +2.0%] (maybe worse)
startup:petclinic:tracing:Agent 15.25 s 16.19 s [-12.1%; +0.5%] (unstable)

Commit: d5e91fe1 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

This branch has not been deployed

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

Labels

inst: spring Spring instrumentation tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes type: bug fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant