Skip to content

fix(client): detect streamed ClickHouse exceptions#331

Open
simPod wants to merge 10 commits into
masterfrom
fix/detect-streamed-clickhouse-exceptions
Open

fix(client): detect streamed ClickHouse exceptions#331
simPod wants to merge 10 commits into
masterfrom
fix/detect-streamed-clickhouse-exceptions

Conversation

@simPod

@simPod simPod commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • detect ClickHouse streamed exception blocks in HTTP 200 response bodies before output parsing
  • preserve non-streaming response bodies after inspection for sync clients
  • add regression coverage for sync and async clients plus ServerError parsing

Notes

  • selectStream remains unbuffered and does not pre-scan the body, because that would consume or buffer the stream.

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.57%. Comparing base (af24f65) to head (22e74d9).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #331      +/-   ##
==========================================
+ Coverage   94.33%   94.57%   +0.23%     
==========================================
  Files          42       42              
  Lines         742      774      +32     
==========================================
+ Hits          700      732      +32     
  Misses         42       42              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves error handling by detecting ClickHouse “streamed exception” blocks that can appear inside HTTP 200 response bodies, ensuring sync/async clients raise ServerError before attempting to parse output.

Changes:

  • Extend ServerError parsing and add ServerError::bodyContainsStreamedException() for streamed exception detection.
  • Add streamed-exception detection to both PsrClickHouseClient and PsrClickHouseAsyncClient for HTTP 200 responses (with opt-out for selectStream).
  • Add regression tests covering streamed exception detection and parsing for sync/async clients.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Exception/ServerErrorTest.php Adds parsing/detection coverage for streamed exception bodies.
tests/Client/PsrClickHouseClientStreamedExceptionTest.php Adds sync/async client regression tests for streamed exception handling and selectStream behavior.
src/Exception/ServerError.php Improves error code parsing to match “Code:” not only at start and adds streamed exception detection helper.
src/Client/PsrClickHouseClient.php Adds streamed exception detection for HTTP 200 responses (disabled for streaming select).
src/Client/PsrClickHouseAsyncClient.php Adds streamed exception detection for HTTP 200 responses in async flow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Client/PsrClickHouseClient.php Outdated
Comment on lines 363 to 373
$bodyContent = $response->getBody()->__toString();
if (
ServerError::bodyContainsStreamedException(
$bodyContent,
$response->getHeaderLine('X-ClickHouse-Exception-Tag'),
)
) {
throw ServerError::fromResponse($response);
}

return $response;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Addressed in 804ee0d. The inspected body is now captured into a fresh string-backed response body before returning or throwing, so non-seekable streams are not lost after detection. Added regression coverage using a non-seekable read-once stream.

Comment thread src/Client/PsrClickHouseAsyncClient.php Outdated
Comment on lines +116 to +124
$bodyContent = $response->getBody()->__toString();
if (
ServerError::bodyContainsStreamedException(
$bodyContent,
$response->getHeaderLine('X-ClickHouse-Exception-Tag'),
)
) {
throw ServerError::fromResponse($response);
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Addressed in 804ee0d. Async detection now also replaces the consumed response body with a fresh stream before reusing the ResponseInterface, with non-seekable stream coverage in the async regression test.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread src/Client/PsrClickHouseClient.php Outdated
Comment on lines +388 to +389
fwrite($body, $bodyContent);
rewind($body);
Comment thread src/Client/PsrClickHouseAsyncClient.php Outdated
Comment on lines +149 to +150
fwrite($body, $bodyContent);
rewind($body);
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