Skip to content

Commit 7b20f0d

Browse files
committed
feat: enhance error handling in ChromaApi with detailed logging for not found exceptions
Signed-off-by: liugddx <[email protected]>
1 parent 5c7a994 commit 7b20f0d

File tree

1 file changed

+59
-4
lines changed
  • vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore

1 file changed

+59
-4
lines changed

vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaApi.java

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ public static Builder builder() {
6868
// Regular expression pattern that looks for a message.
6969
private static final Pattern MESSAGE_ERROR_PATTERN = Pattern.compile("\"message\":\"(.*?)\"");
7070

71+
// Regular expression pattern that looks for NotFoundError in JSON error response.
72+
private static final Pattern NOT_FOUND_ERROR_PATTERN = Pattern.compile("NotFoundError\\('([^']*)'\\)");
73+
7174
private static final String X_CHROMA_TOKEN_NAME = "x-chroma-token";
7275

7376
private final ObjectMapper objectMapper;
@@ -144,7 +147,13 @@ public Tenant getTenant(String tenantName) {
144147
}
145148
catch (HttpClientErrorException e) {
146149
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
147-
logger.debug("Tenant [{}] does not exist, returning null", tenantName);
150+
String errorMessage = this.getErrorMessage(e);
151+
if (StringUtils.hasText(errorMessage)) {
152+
logger.debug("Tenant [{}] does not exist: {}, returning null", tenantName, errorMessage);
153+
}
154+
else {
155+
logger.debug("Tenant [{}] does not exist, returning null", tenantName);
156+
}
148157
return null;
149158
}
150159
throw new RuntimeException(this.getErrorMessage(e), e);
@@ -176,7 +185,15 @@ public Database getDatabase(String tenantName, String databaseName) {
176185
}
177186
catch (HttpClientErrorException e) {
178187
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
179-
logger.debug("Database [{}] in tenant [{}] does not exist, returning null", databaseName, tenantName);
188+
String errorMessage = this.getErrorMessage(e);
189+
if (StringUtils.hasText(errorMessage)) {
190+
logger.debug("Database [{}] in tenant [{}] does not exist: {}, returning null", databaseName,
191+
tenantName, errorMessage);
192+
}
193+
else {
194+
logger.debug("Database [{}] in tenant [{}] does not exist, returning null", databaseName,
195+
tenantName);
196+
}
180197
return null;
181198
}
182199
throw new RuntimeException(this.getErrorMessage(e), e);
@@ -240,8 +257,16 @@ public Collection getCollection(String tenantName, String databaseName, String c
240257
}
241258
catch (HttpClientErrorException e) {
242259
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
243-
logger.debug("Collection [{}] in database [{}] and tenant [{}] does not exist, returning null",
244-
collectionName, databaseName, tenantName);
260+
String errorMessage = this.getErrorMessage(e);
261+
if (StringUtils.hasText(errorMessage)) {
262+
logger.debug(
263+
"Collection [{}] in database [{}] and tenant [{}] does not exist: {}, returning null",
264+
collectionName, databaseName, tenantName, errorMessage);
265+
}
266+
else {
267+
logger.debug("Collection [{}] in database [{}] and tenant [{}] does not exist, returning null",
268+
collectionName, databaseName, tenantName);
269+
}
245270
return null;
246271
}
247272
throw new RuntimeException(this.getErrorMessage(e), e);
@@ -343,6 +368,27 @@ private void httpHeaders(HttpHeaders headers) {
343368
}
344369

345370
private String getErrorMessage(HttpStatusCodeException e) {
371+
// First, try to parse the response body as JSON error response
372+
String responseBody = e.getResponseBodyAsString();
373+
if (StringUtils.hasText(responseBody)) {
374+
try {
375+
ErrorResponse errorResponse = this.objectMapper.readValue(responseBody, ErrorResponse.class);
376+
if (errorResponse.error() != null) {
377+
// Extract error message from NotFoundError('message') format
378+
Matcher notFoundErrorMatcher = NOT_FOUND_ERROR_PATTERN.matcher(errorResponse.error());
379+
if (notFoundErrorMatcher.find()) {
380+
return notFoundErrorMatcher.group(1);
381+
}
382+
// Return the error as-is if it doesn't match NotFoundError pattern
383+
return errorResponse.error();
384+
}
385+
}
386+
catch (JsonProcessingException ex) {
387+
// If JSON parsing fails, fall back to pattern matching on the response body
388+
logger.debug("Failed to parse error response as JSON, falling back to pattern matching", ex);
389+
}
390+
}
391+
346392
var errorMessage = e.getMessage();
347393

348394
// If the error message is empty or null, return an empty string
@@ -638,6 +684,15 @@ private static class CollectionList extends ArrayList<Collection> {
638684

639685
}
640686

687+
/**
688+
* Chroma API error response.
689+
*
690+
* @param error The error message from Chroma API.
691+
*/
692+
@JsonInclude(JsonInclude.Include.NON_NULL)
693+
private record ErrorResponse(@JsonProperty("error") String error) {
694+
}
695+
641696
public static final class Builder {
642697

643698
private String baseUrl = ChromaApiConstants.DEFAULT_BASE_URL;

0 commit comments

Comments
 (0)