SOLR-11431: Report 503 instead of 500 for a core that fails to initialize - #5002
Open
nick-boss-tech wants to merge 10 commits into
Open
nick-boss-tech wants to merge 10 commits into
nick-boss-tech wants to merge 10 commits into
Conversation
ShardResponse.getException() returns Throwable; the extracted helper took Exception and did not compile.
Drive real ShardResponse objects through PeerSync.handleResponse: a failed core (SolrCoreInitializationException) and a 404 count as success for GET_VERSIONS when cantReachIsSuccess, a 500 does not, and the failed-core response is not tolerated for GET_UPDATES or when cantReachIsSuccess is false. handleResponse becomes package-visible for testing, and the two ShardResponse setters the test needs become public, mirroring the SOLR-7550 branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 AI text below 🤖 (posted on behalf of Nick Shanin)
https://issues.apache.org/jira/browse/SOLR-11431
What happens today
A core that fails to initialize answers requests with a 500:
SolrCoreInitializationExceptionis built withSERVER_ERROR. During leader election,PeerSynctreats that 500 as a failed version request, so a replica whose core never came up can fail the election for its shard. The election is built to tolerate a replica that cannot answer:SyncStrategycreates the electionPeerSyncwithcantReachIsSuccess = true, so an unreachable replica counts as success and is reconciled later by recovery. A core that failed to initialize still has its index and transaction log on disk and may hold the most up-to-date copy; it is simply another replica that cannot answer right now, and a 404 from it is already tolerated. The status is also wrong in itself: the core is unavailable, not mishandling the request.What this change does
SolrCoreInitializationExceptionnow reports 503 (SERVICE_UNAVAILABLE) instead of 500. A stale comment inCoreContaineris corrected to match, and the threeTestCoreContainerexpectations move from 500 to 503.PeerSyncneeds no new tolerance: it already counts a 503 or 404 answer to aGET_VERSIONSrequest as success during leader election whencantReachIsSuccessis set. The onlyPeerSyncedit extracts that existing check as the test-visible predicateisToleratedLeaderElectionException, with the same conditions and the same truth table, andPeerSyncLeaderElectionTestpins the predicate directly. A 500 still fails, and failures onGET_UPDATESrequests still fail.PeerSyncFailedCoreResponseTestdrives realShardResponseobjects throughPeerSync.handleResponse(the response class is final, so it is built, not mocked): the failed-core 503 and the 404 count as success, the 500 does not, and nothing is tolerated forGET_UPDATESor withcantReachIsSuccessoff. Making that wiring test possible is the reasonhandleResponsebecomes package-visible and twoShardResponsesetters (setException,setShardAddress) become public: the test has to construct real responses and pass them through the handler.Proof
Verified at head 84a2aa8 on 2026-10-04.
TestCoreContainer: 25 tests, 0 failures, 3 skipped at this head, including the three expectations that move from 500 to 503.TestCoreContaineragainst base production code fails intestCoreInitFailuresFromEmptyContainerandtestCoreInitFailuresOnReloadwith "expected:<503> but was:<500>", so the status change itself has a fails-on-base proof.PeerSyncFailedCoreResponseTest: 5 of 5 pass. A fails-on-base run is not possible for the new PeerSync tests: they exerciseisToleratedLeaderElectionExceptionand a test-visiblehandleResponse, both added by this PR, so they do not compile against the base tree.PeerSyncLeaderElectionTestandTestLazyCoresgreen, with tidy and Error Prone clean.Limits
SolrCoreInitializationExceptionsurfaces, and other consumers change behavior with it.SolrCmdDistributor.checkRetryretries a forwarded update on 404, 403, or 503, so an update forwarded to a replica whose core failed to initialize, a non-retried 500 on base, is now retried.CloudSolrClienttreats a 503 like a 404 in its stale-state retry and expires the cached collection state, so a request routed to a failed-init core now triggers that refresh where the 500 did not. Both fit an unavailable core, but they are behavior changes and are stated here rather than left to be found.ResponseUtils.getErrorInfoattaches the stack trace to the error body only for code 500 (or below 100) and logs"500 Exception"at ERROR only for those codes, so a request to a core that failed to initialize now returns the message without the trace and is not logged at ERROR there. The message itself still names the init failure and its cause./getversion request with 503. The PeerSync tests construct the exception and the responses locally; the status mapping is covered at the container level byTestCoreContainer. The election failure described above is likewise a reading of the code, not a reproduced one: no test, on base or at this head, elects a leader with a failed core in the shard." is still loading"), not any 503. A failed-init core's message is"not available due to init failure: "followed by the underlying cause, which does not carry that suffix on its own, so this 503 does not trigger the retry today; a cause whose own text happened to contain the suffix would be retried. If that matching ever loosens to any 503, the two changes would interact.cantReachIsSuccess.Changelog:
changelog/unreleased/SOLR-11431.ymlAI assistance
AI agents assisted with research, implementation, review, and drafting. Nick Shanin directed the work and takes responsibility for this contribution.