Skip to content

Commit b76245d

Browse files
Deserialize error details
1 parent 7f9b0c8 commit b76245d

File tree

18 files changed

+2089
-15
lines changed

18 files changed

+2089
-15
lines changed

databricks-sdk-java/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
<artifactId>jackson-datatype-jsr310</artifactId>
105105
<version>${jackson.version}</version>
106106
</dependency>
107+
<!-- Jackson Guava module needed to serialize/deserialize AutoValue classes -->
108+
<dependency>
109+
<groupId>com.fasterxml.jackson.datatype</groupId>
110+
<artifactId>jackson-datatype-guava</artifactId>
111+
<version>${jackson.version}</version>
112+
</dependency>
107113
<!-- Google Auto Value -->
108114
<dependency>
109115
<groupId>com.google.auto.value</groupId>

databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksError.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
* unrecoverable way and this exception should be thrown, potentially wrapped in another exception.
1515
*/
1616
public class DatabricksError extends DatabricksException {
17-
private static final String ERROR_INFO_TYPE = "type.googleapis.com/google.rpc.ErrorInfo";
18-
private final String message;
1917
private final Throwable cause;
2018
private final String errorCode;
2119
private final int statusCode;
@@ -51,14 +49,13 @@ private DatabricksError(
5149
List<ErrorDetail> details) {
5250
super(message, cause);
5351
this.errorCode = errorCode;
54-
this.message = message;
5552
this.cause = cause;
5653
this.statusCode = statusCode;
5754
this.details = details == null ? Collections.emptyList() : details;
5855
}
5956

6057
public List<ErrorDetail> getErrorInfo() {
61-
return this.getDetailsByType(ERROR_INFO_TYPE);
58+
return this.getDetailsByType("type.googleapis.com/google.rpc.ErrorInfo");
6259
}
6360

6461
public String getErrorCode() {

databricks-sdk-java/src/main/java/com/databricks/sdk/core/error/ApiErrorBody.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import com.databricks.sdk.core.error.details.ErrorDetails;
56
import java.util.List;
7+
import java.util.Arrays;
8+
import java.util.Collections;
69

710
/**
811
* The union of all JSON error responses from the Databricks APIs, not including HTML responses.
@@ -28,14 +31,14 @@ public ApiErrorBody(
2831
@JsonProperty("status") String scimStatus,
2932
@JsonProperty("scimType") String scimType,
3033
@JsonProperty("error") String api12Error,
31-
@JsonProperty("details") List<ErrorDetail> errorDetails) {
34+
@JsonProperty("details") ErrorDetails errorDetails) {
3235
this.errorCode = errorCode;
3336
this.message = message;
3437
this.scimDetail = scimDetail;
3538
this.scimStatus = scimStatus;
3639
this.scimType = scimType;
3740
this.api12Error = api12Error;
38-
this.errorDetails = errorDetails;
41+
this.errorDetails = fromDetails(errorDetails);
3942
}
4043

4144
public List<ErrorDetail> getErrorDetails() {
@@ -93,4 +96,14 @@ public String getApi12Error() {
9396
public void setApi12Error(String api12Error) {
9497
this.api12Error = api12Error;
9598
}
99+
100+
private static List<ErrorDetail> fromDetails(ErrorDetails details) {
101+
if (details == null) {
102+
return Collections.emptyList();
103+
}
104+
if (!details.errorInfo().isPresent()) {
105+
return Collections.emptyList();
106+
}
107+
return Arrays.asList(new ErrorDetail("type.googleapis.com/google.rpc.ErrorInfo", details.errorInfo().get().reason(), details.errorInfo().get().domain(), details.errorInfo().get().metadata()));
108+
}
96109
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package com.databricks.sdk.core.error.details;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
6+
import com.google.auto.value.AutoValue;
7+
import java.util.List;
8+
9+
/**
10+
* BadRequest describes violations in a client request. This error type focuses
11+
* on the syntactic aspects of the request.
12+
*
13+
* <p>BadRequest errors occur when the request format, structure, or content
14+
* does not meet the service's requirements. This is different from business
15+
* logic errors or system failures - it specifically indicates that the client
16+
* sent a malformed or invalid request.
17+
*
18+
* <p>Examples of bad request violations might include:
19+
* <ul>
20+
* <li>Missing required fields</li>
21+
* <li>Invalid field values (wrong type, format, or range)</li>
22+
* <li>Malformed JSON or XML</li>
23+
* <li>Unsupported field combinations</li>
24+
* <li>Invalid enum values</li>
25+
* <li>Field length or size violations</li>
26+
* </ul>
27+
*
28+
* <p>This information helps clients:
29+
* <ul>
30+
* <li>Identify what's wrong with their request</li>
31+
* <li>Fix the request format before retrying</li>
32+
* <li>Understand the service's input requirements</li>
33+
* <li>Implement proper input validation</li>
34+
* </ul>
35+
*/
36+
@AutoValue
37+
@JsonDeserialize(builder = AutoValue_BadRequest.Builder.class)
38+
@JsonIgnoreProperties(ignoreUnknown = true)
39+
public abstract class BadRequest {
40+
41+
/**
42+
* Describes all field violations in the request.
43+
*
44+
* <p>This list contains details about each specific field or aspect of
45+
* the request that violated the service's requirements. Multiple violations
46+
* can occur if the request has multiple problems.
47+
*
48+
* @return the list of field violations
49+
*/
50+
@JsonProperty("field_violations")
51+
public abstract List<BadRequestFieldViolation> fieldViolations();
52+
53+
/**
54+
* Creates a new builder for constructing BadRequest instances.
55+
*
56+
* @return a new builder instance
57+
*/
58+
public static Builder builder() {
59+
return new AutoValue_BadRequest.Builder();
60+
}
61+
62+
/**
63+
* Builder for constructing BadRequest instances.
64+
*/
65+
@AutoValue.Builder
66+
@JsonIgnoreProperties(ignoreUnknown = true)
67+
public abstract static class Builder {
68+
69+
/**
70+
* Sets the field violations.
71+
*
72+
* @param fieldViolations the list of field violations
73+
* @return this builder for method chaining
74+
*/
75+
@JsonProperty("field_violations")
76+
public abstract Builder fieldViolations(List<BadRequestFieldViolation> fieldViolations);
77+
78+
/**
79+
* Builds the BadRequest instance.
80+
*
81+
* @return a new BadRequest instance
82+
*/
83+
public abstract BadRequest build();
84+
}
85+
86+
/**
87+
* BadRequestFieldViolation describes a specific field violation in a request.
88+
*
89+
* <p>Each violation provides details about what specific field or aspect
90+
* of the request was invalid and how the client can fix it.
91+
*/
92+
@AutoValue
93+
@JsonDeserialize(builder = AutoValue_BadRequest_BadRequestFieldViolation.Builder.class)
94+
@JsonIgnoreProperties(ignoreUnknown = true)
95+
public abstract static class BadRequestFieldViolation {
96+
97+
/**
98+
* A path leading to a field in the request body.
99+
*
100+
* <p>This field identifies the specific location of the violation
101+
* within the request structure. The path format depends on the request
102+
* format but typically follows a hierarchical structure.
103+
*
104+
* <p>Examples of field paths:
105+
* <ul>
106+
* <li>"name" - top-level field</li>
107+
* <li>"user.email" - nested field</li>
108+
* <li>"items[0].id" - array element field</li>
109+
* <li>"metadata.api_key" - deeply nested field</li>
110+
* <li>"settings.notifications.enabled" - multi-level nested field</li>
111+
* </ul>
112+
*
113+
* <p>This path helps clients quickly locate and fix the problematic
114+
* field in their request.
115+
*
116+
* @return the path to the violating field
117+
*/
118+
@JsonProperty("field")
119+
public abstract String field();
120+
121+
/**
122+
* A description of why the request element is bad.
123+
*
124+
* <p>This field provides a human-readable explanation of what's wrong
125+
* with the field and how to fix it. The description should be clear
126+
* enough for developers to understand and resolve the issue.
127+
*
128+
* <p>Examples of field violation descriptions:
129+
* <ul>
130+
* <li>"Field is required and cannot be empty"</li>
131+
* <li>"Value must be a positive integer"</li>
132+
* <li>"Invalid email format"</li>
133+
* <li>"String length must be between 1 and 100 characters"</li>
134+
* <li>"Unsupported enum value. Must be one of: [A, B, C]"</li>
135+
* <li>"Field cannot contain special characters"</li>
136+
* <li>"Date must be in ISO 8601 format (YYYY-MM-DD)"</li>
137+
* </ul>
138+
*
139+
* @return description of why the field is invalid
140+
*/
141+
@JsonProperty("description")
142+
public abstract String description();
143+
144+
/**
145+
* Creates a new builder for constructing BadRequestFieldViolation instances.
146+
*
147+
* @return a new builder instance
148+
*/
149+
public static Builder builder() {
150+
return new AutoValue_BadRequest_BadRequestFieldViolation.Builder();
151+
}
152+
153+
/**
154+
* Builder for constructing BadRequestFieldViolation instances.
155+
*/
156+
@AutoValue.Builder
157+
@JsonIgnoreProperties(ignoreUnknown = true)
158+
public abstract static class Builder {
159+
160+
/**
161+
* Sets the field path.
162+
*
163+
* @param field the path to the violating field
164+
* @return this builder for method chaining
165+
*/
166+
@JsonProperty("field")
167+
public abstract Builder field(String field);
168+
169+
/**
170+
* Sets the violation description.
171+
*
172+
* @param description description of why the field is invalid
173+
* @return this builder for method chaining
174+
*/
175+
@JsonProperty("description")
176+
public abstract Builder description(String description);
177+
178+
/**
179+
* Builds the BadRequestFieldViolation instance.
180+
*
181+
* @return a new BadRequestFieldViolation instance
182+
*/
183+
public abstract BadRequestFieldViolation build();
184+
}
185+
}
186+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com.databricks.sdk.core.error.details;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
6+
import com.google.auto.value.AutoValue;
7+
import java.util.List;
8+
9+
/**
10+
* DebugInfo describes additional debugging information.
11+
*
12+
* <p>This class provides detailed information that can be used by developers
13+
* and support teams to understand what went wrong and where the error occurred.
14+
* The information is typically more technical and detailed than what would be
15+
* shown to end users.
16+
*
17+
* <p>DebugInfo is particularly useful for:
18+
* <ul>
19+
* <li>Development and testing environments</li>
20+
* <li>Support ticket investigations</li>
21+
* <li>System debugging and troubleshooting</li>
22+
* <li>Understanding the root cause of errors</li>
23+
* </ul>
24+
*/
25+
@AutoValue
26+
@JsonDeserialize(builder = AutoValue_DebugInfo.Builder.class)
27+
@JsonIgnoreProperties(ignoreUnknown = true)
28+
public abstract class DebugInfo {
29+
30+
/**
31+
* The stack trace entries indicating where the error occurred.
32+
*
33+
* <p>This list contains the call stack at the time the error occurred,
34+
* typically starting from the most recent call and going backwards through
35+
* the call chain. Each entry usually represents a method call or function
36+
* invocation.
37+
*
38+
* <p>Stack trace information is invaluable for:
39+
* <ul>
40+
* <li>Identifying the exact location where an error occurred</li>
41+
* <li>Understanding the execution path that led to the error</li>
42+
* <li>Debugging complex error scenarios</li>
43+
* <li>Providing context to support teams</li>
44+
* </ul>
45+
*
46+
* @return the stack trace entries
47+
*/
48+
@JsonProperty("stack_entries")
49+
public abstract List<String> stackEntries();
50+
51+
/**
52+
* Additional debugging information provided by the server.
53+
*
54+
* <p>This field can contain any additional context or details that the
55+
* server deems useful for debugging purposes. The exact content depends
56+
* on the service implementation and the specific error that occurred.
57+
*
58+
* <p>Examples of additional debugging information might include:
59+
* <ul>
60+
* <li>Internal error codes or identifiers</li>
61+
* <li>System state information</li>
62+
* <li>Configuration details</li>
63+
* <li>Performance metrics</li>
64+
* <li>Other diagnostic data</li>
65+
* </ul>
66+
*
67+
* @return additional debugging information
68+
*/
69+
@JsonProperty("detail")
70+
public abstract String detail();
71+
72+
/**
73+
* Creates a new builder for constructing DebugInfo instances.
74+
*
75+
* @return a new builder instance
76+
*/
77+
public static Builder builder() {
78+
return new AutoValue_DebugInfo.Builder();
79+
}
80+
81+
/**
82+
* Builder for constructing DebugInfo instances.
83+
*/
84+
@AutoValue.Builder
85+
@JsonIgnoreProperties(ignoreUnknown = true)
86+
public abstract static class Builder {
87+
88+
/**
89+
* Sets the stack trace entries.
90+
*
91+
* @param stackEntries the stack trace entries
92+
* @return this builder for method chaining
93+
*/
94+
@JsonProperty("stack_entries")
95+
public abstract Builder stackEntries(List<String> stackEntries);
96+
97+
/**
98+
* Sets the additional debugging information.
99+
*
100+
* @param detail additional debugging information
101+
* @return this builder for method chaining
102+
*/
103+
@JsonProperty("detail")
104+
public abstract Builder detail(String detail);
105+
106+
/**
107+
* Builds the DebugInfo instance.
108+
*
109+
* @return a new DebugInfo instance
110+
*/
111+
public abstract DebugInfo build();
112+
}
113+
}

0 commit comments

Comments
 (0)