Skip to content

fix(polaris): prevent nil pointer panic when route rules don't match#3313

Open
cvictory wants to merge 1 commit into
developfrom
fix/polaris-nil-invoker-panic-3303
Open

fix(polaris): prevent nil pointer panic when route rules don't match#3313
cvictory wants to merge 1 commit into
developfrom
fix/polaris-nil-invoker-panic-3303

Conversation

@cvictory
Copy link
Copy Markdown
Contributor

Bug

  • Symptom: When Polaris only has uid-based route rules without discovery fallback, consumer gets RouteRuleNotMatch followed by nil pointer panic.
  • Root cause: Route() in cluster/router/polaris/router.go returns an empty invoker slice when ProcessRouters returns instances that don't map to any known invoker. The empty slice propagates to cluster invokers (failfast, failover, etc.) which access invokers[0], causing nil pointer panic.

Fix

After building the result from ProcessRouters response, if the result is empty (no matching invokers), log a warning and return the original invokers as a safe fallback. This follows the same defensive pattern used in 5 other error paths in the same method.

Changed files:

  • cluster/router/polaris/router.go — 4-line empty-result guard
  • cluster/router/polaris/router_test.go — 7 new regression tests with mock infrastructure

Verification

  • Tests: 13/13 pass (6 existing + 7 new)
  • go vet: clean
  • go build: clean
  • Key regression tests:
    • TestRouteRuleNotMatchFallbackToOriginalInvokers — non-matching instances → fallback
    • TestRouteEmptyProcessRoutersResultFallbackToOriginalInvokers — empty result → fallback
    • TestRouteHappyPathReturnsMatchedInvokers — matching instances → filtered (behavior preserved)

Closes #3303

…3303)

When Polaris route rules don't match (e.g., uid-only rules without
discovery fallback), Route() could return an empty invoker slice,
causing nil pointer panic in downstream cluster invokers.

Add empty-result guard after ProcessRouters: if no invokers match
the routed instances, fall back to original invokers with a warning
log instead of returning an empty slice.

Closes #3303
@sonarqubecloud
Copy link
Copy Markdown

@AlexStocks AlexStocks changed the base branch from main to develop April 29, 2026 13:01
}
}

if len(ret) == 0 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] len(ret)==0 时直接回退到 invokers 会绕过真正生效的 Polaris 路由规则。ret 为空并不只代表“实例 ID 映射不上”,也可能是路由规则故意把当前请求全部过滤掉;这时正确行为应该是返回空结果并让上层按“无可用 provider”处理,而不是把原始 invokers 全部放回来继续发流量。现在的实现会把本应被路由规则拦掉的请求重新打到 provider 上,属于治理语义错误。

}
}

if len(ret) == 0 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] len(ret)==0 时直接回退到 invokers 会绕过真正生效的 Polaris 路由规则。ret 为空并不只代表“实例 ID 映射不上”,也可能是路由规则故意把当前请求全部过滤掉;这时正确行为应该是返回空结果并让上层按“无可用 provider”处理,而不是把原始 invokers 全部放回来继续发流量。现在的实现会把本应被路由规则拦掉的请求重新打到 provider 上,属于治理语义错误。

@Alanxtl Alanxtl added the 3.3.2 version 3.3.2 label Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.3.2 version 3.3.2 ☢️ Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Polaris uid-only route rule 未命中时会打空 invoker 并触发 nil pointer panic

3 participants