fix(router): guard against nil context in getResponseHeaderPropagation#2544
fix(router): guard against nil context in getResponseHeaderPropagation#2544stakeswky wants to merge 1 commit intowundergraph:mainfrom
Conversation
WalkthroughAdds a nil-check in getResponseHeaderPropagation to return nil when passed a nil context, and adds a regression test ensuring the function does not panic and returns nil for a nil context. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi @stakeswky, thanks for your contribution, we'll take a look. cc @jensneuse |
|
Thanks! Let me know if you have any questions or feedback. |
|
Hi @stakeswky, would you mind updating this PR to the latest main and seeing if the test still fails? I believe we addressed the root cause of this last week. |
|
Or, seeing that the test will absolutely still fail, can you retry your original issue? |
Add a nil check for the context parameter before calling ctx.Value() in getResponseHeaderPropagation(). When a fetch path completes with a nil context.Context, the router panics with a nil pointer dereference at header_rule_engine.go:58, returning a 500 to the client. With this guard, a nil context is treated as a no-op (returns nil propagation), which causes ApplyResponseHeaderRules to return early without applying any header rules — matching the expected behavior described in the issue. Fixes wundergraph#2530
adf9941 to
d617274
Compare
|
Rebased onto the latest |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
router/core/header_rule_engine_test.go (1)
339-347: Consider moving the nil-return assertion outside theNotPanicsclosure.Nesting
assert.Nilinsideassert.NotPanicsis logically correct but slightly muddied: if a panic does occur, the closure is interrupted beforeassert.Nilruns and onlyNotPanicsfails — the nil-return assertion silently becomes unreachable. Pulling it out makes both assertions independently visible in test output and easier to read.♻️ Proposed refactor
- assert.NotPanics(t, func() { - result := getResponseHeaderPropagation(nil) - assert.Nil(t, result) - }) + var result *responseHeaderPropagation + assert.NotPanics(t, func() { + result = getResponseHeaderPropagation(nil) + }) + assert.Nil(t, result)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@router/core/header_rule_engine_test.go` around lines 339 - 347, The test currently calls getResponseHeaderPropagation(nil) and asserts nil inside the assert.NotPanics closure; change it so the call is still wrapped by assert.NotPanics but the result is assigned to an outer scoped variable (e.g. var result interface{}; assert.NotPanics(t, func(){ result = getResponseHeaderPropagation(nil) })), and then perform assert.Nil(t, result) outside the NotPanics closure so both the panic-check and the nil-return assertion are reported independently; update TestGetResponseHeaderPropagation_NilContext accordingly, referencing getResponseHeaderPropagation and the test function name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@router/core/header_rule_engine_test.go`:
- Around line 339-347: The test currently calls
getResponseHeaderPropagation(nil) and asserts nil inside the assert.NotPanics
closure; change it so the call is still wrapped by assert.NotPanics but the
result is assigned to an outer scoped variable (e.g. var result interface{};
assert.NotPanics(t, func(){ result = getResponseHeaderPropagation(nil) })), and
then perform assert.Nil(t, result) outside the NotPanics closure so both the
panic-check and the nil-return assertion are reported independently; update
TestGetResponseHeaderPropagation_NilContext accordingly, referencing
getResponseHeaderPropagation and the test function name.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
router/core/header_rule_engine.gorouter/core/header_rule_engine_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- router/core/header_rule_engine.go
|
Hi @stakeswky, are you able to recheck the actual query/plan that prompted you to create this PR? We didn’t guard against nil in the function directly because nil context should never have been passed to this function in the first place, so the panic was justified. I believe this test will still fail because it forces the nil context to be passed directly. We’ve resolved the root issue now, please let us know and create a new issue if you run into any other problems. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2544 +/- ##
===========================================
- Coverage 43.56% 34.13% -9.43%
===========================================
Files 1030 225 -805
Lines 143745 24942 -118803
Branches 8941 0 -8941
===========================================
- Hits 62617 8514 -54103
+ Misses 79435 15356 -64079
+ Partials 1693 1072 -621
🚀 New features to boost your workflow:
|
|
Closing for now, please feel free to reopen as an issue if your problem is unresolved |
Summary
Fixes #2530
The router panics with
runtime error: invalid memory address or nil pointer dereferenceingetResponseHeaderPropagationwhen a fetch path completes with a nilcontext.Context. This happens becausectx.Value()is called without checking ifctxis nil first.Changes
router/core/header_rule_engine.goctxparameter ingetResponseHeaderPropagation()ctxis nil, returnsnil(no-op), which causesApplyResponseHeaderRulesto return early — matching the expected behaviorrouter/core/header_rule_engine_test.goTestGetResponseHeaderPropagation_NilContextto verify nil context does not panicRoot Cause
As described in the issue, certain query plan variants can result in a fetch path completing with a nil context. The
OnFinishedhook inengine_loader_hooks.gothen callsApplyResponseHeaderRuleswhich callsgetResponseHeaderPropagation(ctx), andctx.Value()panics on nil receiver.Before / After
Before: Router panics → 500 error → recovery middleware catches it
After: Nil context treated as no-op → response returned normally (no header propagation applied)
Summary by CodeRabbit
Bug Fixes
Tests