Skip to content

fix: write error handling - #425

Open
NguyenHoangSon96 wants to merge 1 commit into
mainfrom
fix/write-error-handling
Open

fix: write error handling#425
NguyenHoangSon96 wants to merge 1 commit into
mainfrom
fix/write-error-handling

Conversation

@NguyenHoangSon96

@NguyenHoangSon96 NguyenHoangSon96 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Closes #

Proposed Changes

Briefly describe your proposed changes:

Changes

  • Reduce the call of objectMapper.readTree(body) function to only one time.

Checklist

  • CHANGELOG.md updated
  • Rebased/mergeable
  • A test has been added if appropriate
  • Tests pass
  • Commit messages are conventional
  • Sign CLA (if not already signed)

@NguyenHoangSon96 NguyenHoangSon96 self-assigned this Aug 20, 2026
@NguyenHoangSon96
NguyenHoangSon96 force-pushed the fix/write-error-handling branch from ca5ff0d to 78953cb Compare August 21, 2026 08:31
@NguyenHoangSon96
NguyenHoangSon96 marked this pull request as ready for review August 21, 2026 15:07
Copilot AI lite review requested due to automatic review settings August 21, 2026 15:07

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 refactors how RestClient formats and classifies write-related HTTP error responses (notably InfluxDB 3 write/partial-write formats), and updates unit/integration tests to reflect the new behavior.

Changes:

  • Added an overloaded RestClient.request(...) that propagates acceptPartial / useV2Api flags so partial-write handling can be gated by client options.
  • Reworked write-error parsing to build InfluxDBPartialWriteException details from JSON responses (and adjusted expected messages in tests).
  • Introduced a small Utils.isNumeric helper and expanded unit test coverage with a table-driven set of partial-write cases.

Reviewed changes

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

Show a summary per file
File Description
src/main/java/com/influxdb/v3/client/internal/RestClient.java Refactors error parsing/exception selection for write endpoints; adds partial-write gating logic.
src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java Passes acceptPartial / useV2Api flags into RestClient.request(...) for write calls.
src/main/java/com/influxdb/v3/client/internal/Utils.java Adds numeric-check helper used by error parsing.
src/main/java/com/influxdb/v3/client/InfluxDBPartialWriteException.java Adjusts LineError nullability annotations.
src/test/java/com/influxdb/v3/client/internal/RestClientTest.java Updates and expands tests for partial-write parsing/message formatting.
src/test/java/com/influxdb/v3/client/integration/E2ETest.java Updates integration expectation for non-accept-partial write errors.
Suppressed comments (2)

src/main/java/com/influxdb/v3/client/InfluxDBPartialWriteException.java:83

  • Changing LineError.errorMessage to @Nullable is a public API contract change and it’s inconsistent with current callers (tests and RestClient.createErrorMsgDetails) that treat it as always present. If the intent is still that a line error always has an error message, keep it @Nonnull and avoid propagating nulls to API consumers.

This issue also appears on line 95 of the same file.

        public LineError(@Nullable final Integer lineNumber,
                         @Nullable final String errorMessage,
                         @Nullable final String originalLine) {
            this.lineNumber = lineNumber;
            this.errorMessage = errorMessage;
            this.originalLine = originalLine;

src/main/java/com/influxdb/v3/client/InfluxDBPartialWriteException.java:100

  • If errorMessage() is intended to be always present for a LineError, its accessor should stay @Nonnull to match the API contract and existing usage.
         * @return line-level error message
         */
        @Nullable
        public String errorMessage() {
            return errorMessage;
        }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/main/java/com/influxdb/v3/client/internal/Utils.java Outdated
Comment thread src/main/java/com/influxdb/v3/client/internal/RestClient.java Outdated
Comment thread src/main/java/com/influxdb/v3/client/internal/RestClient.java Outdated
Comment thread src/test/java/com/influxdb/v3/client/internal/RestClientTest.java Outdated
Comment thread src/main/java/com/influxdb/v3/client/internal/RestClient.java Outdated
@NguyenHoangSon96
NguyenHoangSon96 requested a lite review from Copilot August 21, 2026 15:29
@NguyenHoangSon96
NguyenHoangSon96 force-pushed the fix/write-error-handling branch 3 times, most recently from d4a06d2 to 9e7e4cd Compare August 21, 2026 15:33

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 6 out of 6 changed files in this pull request and generated 3 comments.

Suppressed comments (6)

Previously missed (3) — in code that hasn't changed since the last review.

src/main/java/com/influxdb/v3/client/InfluxDBPartialWriteException.java:82

  • InfluxDBPartialWriteException.LineError#errorMessage was previously non-null in the public API contract. Making it @Nullable is a breaking/loosening change for callers and also increases the risk of NPEs in formatting code that assumes a message exists. Unless null is a valid state that callers must handle, keep this @Nonnull.

This issue also appears on line 97 of the same file.

        public LineError(@Nullable final Integer lineNumber,
                         @Nullable final String errorMessage,
                         @Nullable final String originalLine) {
            this.lineNumber = lineNumber;
            this.errorMessage = errorMessage;

src/main/java/com/influxdb/v3/client/internal/RestClient.java:263

  • if (root == null || root.toString().isEmpty()) is effectively dead code (Jackson returns a non-null node, and toString() won’t be empty). As a result, header-based fallbacks won’t execute anymore for empty bodies. Switching this to a body emptiness check restores the intended fallback behavior.
            if (root == null || root.toString().isEmpty()) {
                reason = Stream.of("X-Platform-Error-Code", "X-Influx-Error", "X-InfluxDb-Error")
                        .map(name -> response.headers().firstValue(name).orElse(null))
                        .filter(message -> message != null && !message.isEmpty()).findFirst()
                        .orElse("");

src/main/java/com/influxdb/v3/client/internal/RestClient.java:243

  • The response Content-Type can include parameters (e.g. text/plain; charset=utf-8). Using strict equality here can cause non-JSON text responses to be routed into JSON parsing unnecessarily. Consider a case-insensitive prefix match instead.
            if (contentType != null && contentType.equals("text/plain")) {
                var message = String.format("HTTP status code: %d; Message: %s", statusCode, body);
                throw new InfluxDBApiHttpException(message, response.headers(), response.statusCode());

src/main/java/com/influxdb/v3/client/internal/RestClient.java:336

  • This method return type uses @NonNull (jspecify), which will fail to compile if jspecify isn’t on the classpath and is also inconsistent with the rest of this class’ javax.annotation.Nonnull usage. Use @Nonnull (or omit the redundant annotation) instead.
    @Nonnull
    private @NonNull List<String> createErrorMsgDetails(
            @Nullable final ParseLineErrorResult result,
            @Nullable final JsonNode root
    ) {

src/test/java/com/influxdb/v3/client/internal/RestClientTest.java:1185

  • @NonNull on toString() requires the jspecify dependency (and isn’t providing much value here). Removing the annotation keeps the test independent of that external annotation library.

    @Override
    public @NonNull String toString() {

src/main/java/com/influxdb/v3/client/InfluxDBPartialWriteException.java:99

  • For consistency with the constructor contract and to avoid forcing callers to handle nulls that should never occur, errorMessage() should remain @Nonnull.
        @Nullable
        public String errorMessage() {
            return errorMessage;

Comment thread src/main/java/com/influxdb/v3/client/internal/RestClient.java
Comment thread src/main/java/com/influxdb/v3/client/internal/RestClient.java
Comment thread src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.84071% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.90%. Comparing base (6369d60) to head (5a70263).

Files with missing lines Patch % Lines
...va/com/influxdb/v3/client/internal/RestClient.java 84.90% 5 Missing and 11 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #425      +/-   ##
==========================================
- Coverage   88.73%   87.90%   -0.83%     
==========================================
  Files          21       22       +1     
  Lines        1553     1546       -7     
  Branches      281      277       -4     
==========================================
- Hits         1378     1359      -19     
- Misses         77       83       +6     
- Partials       98      104       +6     

☔ 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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Comment on lines +240 to 243
if ("text/plain".equals(contentType)) {
var message = String.format("HTTP status code: %d; Message: %s", statusCode, body);
throw new InfluxDBApiHttpException(message, response.headers(), response.statusCode());
}
Comment on lines +245 to 251
JsonNode root;
try {
root = objectMapper.readTree(body);
} catch (JsonProcessingException e) {
var message = String.format("HTTP status code: %d; Message: %s", statusCode, body);
throw new InfluxDBApiHttpException(message, response.headers(), response.statusCode());
}
Comment on lines +859 to +865
Assertions.assertThat(testCase.expectedMsg()).as(testCase.name()).isEqualTo(thrown.getMessage());
if (testCase.expectPartial()) {
Assertions.assertThat(thrown).as(testCase.name()).isInstanceOf(InfluxDBPartialWriteException.class);
} else {
Assertions.assertThat(thrown).as(testCase.name()).isInstanceOf(InfluxDBApiHttpException.class);
}
}
Comment on lines +509 to +511

record ParseLineErrorResult(List<InfluxDBPartialWriteException.LineError> lineErrors, boolean allTyped) {
} No newline at end of file
@NguyenHoangSon96
NguyenHoangSon96 force-pushed the fix/write-error-handling branch from 8d12b40 to 4428d3b Compare August 21, 2026 16:31
@NguyenHoangSon96
NguyenHoangSon96 force-pushed the fix/write-error-handling branch from 4428d3b to 5a70263 Compare August 21, 2026 16:31
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