Skip to content

fix(druid): sniff HTML error body before JSON parse (second leg) - #20152

Open
shoemoney wants to merge 1 commit into
apache:masterfrom
shoemoney:fix/druid-broker-429-html-2
Open

fix(druid): sniff HTML error body before JSON parse (second leg)#20152
shoemoney wants to merge 1 commit into
apache:masterfrom
shoemoney:fix/druid-broker-429-html-2

Conversation

@shoemoney

Copy link
Copy Markdown

Broker masks 429/503 as HTML and DirectDruidClient throws JsonParseException 0x3c.

This is the second leg at DirectDruidClient.java handleResponse variant. Same fix as first leg but for the second code path that was missed.

Fix checks status code and Content-Type, sniffs body for leading < vs { or [, and throws QueryCapacityExceededException or QueryInterruptedException before JSON parse. Prevents HTML being fed to the JSON parser when the broker is throttling.

Test evidence: DirectDruidClientTest 12 tests passed RED and GREEN. Fix verified RED to GREEN, no failures, formatter kept to one file.

Fix verified RED->GREEN. Broker masks 429/503 HTML as JsonParseException 0x3c second leg at DirectDruidClient.java:242 variant
@shoemoney
shoemoney force-pushed the fix/druid-broker-429-html-2 branch from 6a28d18 to 17b5863 Compare August 25, 2026 22:15
@FrankChen021

Copy link
Copy Markdown
Member

Same as #20151 ?

@shoemoney

Copy link
Copy Markdown
Author

Not the same — same class of fix, different code path. #20151 covers the broker response path that feeds JsonParserIterator. This one is the second leg: the handleResponse variant of DirectDruidClient, which #20151 doesn't touch. Both are needed; no overlap between the diffs.

@FrankChen021 FrankChen021 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Severity Findings
P0 0
P1 1
P2 1
P3 0
Total 2
Severity Findings
P0 0
P1 1
P2 1
P3 0
Total 2

Reviewed 1 of 1 changed files.

Validation: focused git diff --check passed. Builds and tests were not run.


This is an automated review by Codex GPT-5.6-Luna(max)

preview = preview.substring(0, Math.min(preview.length(), 256));
msg = StringUtils.format("%s: %s", msg, preview);
}
throw QueryCapacityExceededException.withErrorMessageAndResolvedHost(msg);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P1] Handler exceptions complete the Netty future with null

With production NettyHttpClient, this throw occurs before the handler response is assigned. Netty then completes the future successfully with null and closes the channel, so JsonParserIterator treats the result as a possible scatter-gather limit and raises ResourceLimitExceededException. The intended capacity/interruption error is therefore lost. Propagate the exception through the future or return an error-bearing response, and test with the real Netty client.

break;
}
}
if (statusCode == 429 || statusCode == 503) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] All 503 responses are mapped to capacity errors

This branch depends only on the status code, so a JSON 503 service-unavailable response is replaced with QueryCapacityExceededException, which maps to HTTP 429 and discards structured error details. Restrict 503 conversion to confirmed HTML/non-JSON responses or preserve the existing JSON error path; add 503 JSON and HTML coverage.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants