epugh opened a new pull request, #4674:
URL: https://github.com/apache/solr/pull/4674

   ## Summary
   
   Discovered while investigating an intermittent 
`CollectionsApi.GetCollectionStatus` failure under basic-auth-secured clusters 
(used while migrating `bin/solr delete` off ZooKeeper). The endpoint would fail 
intermittently with:
   
   ```
   SEVERE: An exception has been thrown from an exception mapper class 
org.apache.solr.jersey.CatchAllExceptionMapper.
   java.lang.NullPointerException: Cannot invoke 
"org.apache.solr.request.SolrQueryRequest.getCore()" because "req" is null
        at 
org.apache.solr.handler.RequestHandlerBase.processReceivedException(RequestHandlerBase.java:326)
        at 
org.apache.solr.jersey.CatchAllExceptionMapper.processAndRespondToException(CatchAllExceptionMapper.java:93)
   ```
   
   ...cascading into Jersey re-invoking the response filter chain via its 
"already mapped exception" fallback path, which in turn caused 
`RequestMetricHandling.PostRequestMetricsFilter` to call `.stop()` a second 
time on an already-stopped timer — tripping `RTimer`'s `assert state == STARTED 
|| state == PAUSED` (only visible with assertions enabled, e.g. under `-ea` 
test runs; silently harmless in production builds where the assert is compiled 
out).
   
   Root cause: when a request fails before `V2HttpCall` attaches a 
`SolrQueryRequest` to the Jersey request context (the actual trigger appears to 
be a rare race in inter-node request handling — not fully root-caused, but 
independent of any specific endpoint), several Jersey filters/mappers in 
`org.apache.solr.jersey` unconditionally dereference that possibly-null 
`SolrQueryRequest`, causing a *second*, cascading exception while trying to 
handle the first one.
   
   ## Changes
   - `RequestHandlerBase.processReceivedException`: null-check `req` before 
calling `req.getCore()`.
   - `CatchAllExceptionMapper.buildExceptionResponse`: null-check 
`solrQueryRequest` before calling `.getParams()`.
   - `PostRequestDecorationFilter` / `PostRequestLoggingFilter`: null-check 
`solrQueryRequest` before dereferencing (mirrors the existing, correct 
null-check already present in `MediaTypeOverridingFilter`, which had a `// TODO 
Is it valid for SQRequest to be null?` comment confirming this was already a 
known possibility).
   - `RequestMetricHandling.PostRequestMetricsFilter`: guards against being 
invoked more than once for the same request by clearing the `TIMER` property 
after stopping it, so a second (re-entrant) invocation is a no-op instead of 
crashing.
   
   ## Test plan
   - [x] New unit tests: `RequestHandlerBaseTest` (null `req` cases), 
`PostRequestLoggingFilterTest`, `PostRequestDecorationFilterTest` (new), 
`RequestMetricHandlingTest` (new) — each verified to fail without the 
corresponding fix and pass with it (confirmed 
`RequestMetricHandlingTest.testPostRequestMetricsFilterToleratesBeingInvokedTwice`
 fails on `git stash` of just the `RequestMetricHandling.java` fix, passes once 
restored)
   - [x] Existing `CatchAllExceptionMapperTest` (SOLR-18066) still passes — no 
regression to `hideStackTrace` handling
   - [x] Reproduced the original intermittent failure with a throwaway 
integration test hitting `GetCollectionStatus` under a 
`SecurityJson.SIMPLE`-secured 2-node cluster (~40% failure rate over multiple 
runs); with these fixes applied, 15/15 consecutive runs passed
   - [x] `./gradlew :solr:core:spotlessJavaCheck` clean
   - [x] `./gradlew :solr:core:compileJava :solr:core:compileTestJava` clean
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to