Skip to content

Fix error type for non-JSON error responses#758

Merged
renaudhartert-db merged 5 commits intomainfrom
fix/plain-text-error-handling
Apr 14, 2026
Merged

Fix error type for non-JSON error responses#758
renaudhartert-db merged 5 commits intomainfrom
fix/plain-text-error-handling

Conversation

@renaudhartert-db
Copy link
Copy Markdown
Contributor

@renaudhartert-db renaudhartert-db commented Apr 13, 2026

Summary

When the server returns a plain-text error response (e.g. "Invalid Token" with HTTP 403), the SDK throws Unknown instead of PermissionDenied.

The root cause: parseUnknownError derives an error code by splitting response.getStatus() on space, expecting "403 Forbidden". But CommonsHttpClient passes statusLine.getReasonPhrase(), which is just "Forbidden". The split produces one element, so error code defaults to "UNKNOWN", which matches ErrorMapper's error code mapping and short-circuits the status code mapping that would have correctly produced PermissionDenied.

The fix removes the error code derivation entirely. Leaving errorCode null lets AbstractErrorMapper.apply skip the error code mapping and fall through to the status code mapping (403 -> PermissionDenied, 401 -> Unauthenticated, etc.). The error message now uses the raw response body instead of appending Jackson parse exception details.

Behavioral change: non-JSON error responses now produce typed exceptions based on HTTP status code instead of always producing Unknown. The error message no longer contains Jackson deserialization internals.

Test plan

  • New PlainTextErrorTest covers: plain-text 403/401/404, HTML <pre> extraction, empty body, null body
  • Full test suite passes (mvn test -pl databricks-sdk-java)

When the server returns a plain-text error (e.g. "Invalid Token" with
HTTP 403), parseUnknownError set the error code to "UNKNOWN", which
matched ErrorMapper's errorCodeMapping and short-circuited the status
code mapping. This caused all non-JSON errors to produce Unknown instead
of the correct typed exception (PermissionDenied, Unauthenticated, etc.).

The root cause was that parseUnknownError assumed response.getStatus()
returned "403 Forbidden" but it only returns the reason phrase
("Forbidden"). The split-on-space logic always fell into the default
"UNKNOWN" branch.

The fix removes the error code derivation entirely, leaving errorCode
null so AbstractErrorMapper falls through to the status code mapping.
The error message now uses the raw response body instead of appending
Jackson parse exception details.

Co-authored-by: Isaac
Avoid NPE in downstream .equals() and Pattern.matcher() calls
when the error response cannot be parsed as JSON.

Co-authored-by: Isaac
Copy link
Copy Markdown
Contributor

@mihaimitrea-db mihaimitrea-db left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM

The <pre> content extraction was accidentally removed, causing
null error messages for HTML error responses.

Co-authored-by: Isaac
@github-actions
Copy link
Copy Markdown
Contributor

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/sdk-java

Inputs:

  • PR number: 758
  • Commit SHA: 8e6cbe93b48c3c49fc123a11ed8a1e1a81c3b262

Checks will be approved automatically on success.

@renaudhartert-db renaudhartert-db added this pull request to the merge queue Apr 14, 2026
Merged via the queue into main with commit 70ba8a8 Apr 14, 2026
15 of 16 checks passed
@renaudhartert-db renaudhartert-db deleted the fix/plain-text-error-handling branch April 14, 2026 15:11
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