LangChain4j integration for Chroma embedding store enabling storage, retrieval, and similarity search of vector embeddings with metadata filtering support for both API V1 and V2.
—
Comprehensive guide to handling errors when using ChromaEmbeddingStore.
try {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://localhost:8000")
.build();
store.add(embedding);
} catch (java.net.http.HttpConnectTimeoutException e) {
// Cannot connect to Chroma server
System.err.println("Connection failed: " + e.getMessage());
// Action: Check server is running, verify baseUrl
} catch (java.net.ConnectException e) {
// Connection refused
System.err.println("Connection refused: " + e.getMessage());
// Action: Ensure Chroma server is started
}try {
EmbeddingSearchResult<TextSegment> result = store.search(request);
} catch (java.net.http.HttpTimeoutException e) {
// Operation exceeded timeout
System.err.println("Operation timed out: " + e.getMessage());
// Action: Increase timeout or reduce operation size
}try {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
// Missing baseUrl
.collectionName("test")
.build();
} catch (IllegalArgumentException e) {
// Invalid configuration
System.err.println("Configuration error: " + e.getMessage());
// Action: Fix configuration
}public void addDocument(Embedding embedding, TextSegment segment) {
try {
store.add(embedding, segment);
} catch (Exception e) {
System.err.println("Failed to add document: " + e.getMessage());
e.printStackTrace();
}
}public String addWithRetry(
Embedding embedding,
TextSegment segment,
int maxRetries
) {
int attempt = 0;
Exception lastException = null;
while (attempt < maxRetries) {
try {
return store.add(embedding, segment);
} catch (java.net.http.HttpTimeoutException |
java.net.http.HttpConnectTimeoutException e) {
lastException = e;
attempt++;
if (attempt < maxRetries) {
System.out.println("Retry " + attempt + " of " + maxRetries);
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
}
} catch (Exception e) {
// Non-retryable error
throw new RuntimeException("Failed to add document", e);
}
}
throw new RuntimeException(
"Failed after " + maxRetries + " attempts",
lastException
);
}public class CircuitBreakerStore {
private final ChromaEmbeddingStore store;
private int failureCount = 0;
private long lastFailureTime = 0;
private static final int FAILURE_THRESHOLD = 5;
private static final long RESET_TIMEOUT = 60000; // 1 minute
private boolean isCircuitOpen() {
if (failureCount >= FAILURE_THRESHOLD) {
long timeSinceFailure = System.currentTimeMillis() - lastFailureTime;
if (timeSinceFailure < RESET_TIMEOUT) {
return true; // Circuit still open
} else {
// Try to reset
failureCount = 0;
return false;
}
}
return false;
}
public String add(Embedding embedding, TextSegment segment) {
if (isCircuitOpen()) {
throw new RuntimeException("Circuit breaker is open");
}
try {
String id = store.add(embedding, segment);
failureCount = 0; // Reset on success
return id;
} catch (Exception e) {
failureCount++;
lastFailureTime = System.currentTimeMillis();
throw e;
}
}
}public class ResilientRAG {
private final ChromaEmbeddingStore primaryStore;
private final ChromaEmbeddingStore backupStore; // Optional backup
public EmbeddingSearchResult<TextSegment> search(
EmbeddingSearchRequest request
) {
try {
return primaryStore.search(request);
} catch (Exception e) {
System.err.println("Primary store failed: " + e.getMessage());
if (backupStore != null) {
try {
System.out.println("Trying backup store");
return backupStore.search(request);
} catch (Exception backupError) {
System.err.println("Backup store also failed");
}
}
// Return empty result instead of throwing
return new EmbeddingSearchResult<>(Collections.emptyList());
}
}
}try {
// First embedding: 3 dimensions
store.add(Embedding.from(new float[]{0.1f, 0.2f, 0.3f}));
// Second embedding: 4 dimensions (will fail)
store.add(Embedding.from(new float[]{0.1f, 0.2f, 0.3f, 0.4f}));
} catch (RuntimeException e) {
if (e.getMessage().contains("dimension")) {
System.err.println("Embedding dimension mismatch");
// Action: Ensure all embeddings have same dimensions
}
}Prevention:
public class EmbeddingValidator {
private Integer expectedDimension = null;
public void validateAndAdd(Embedding embedding) {
int dimension = embedding.vector().length;
if (expectedDimension == null) {
expectedDimension = dimension;
} else if (dimension != expectedDimension) {
throw new IllegalArgumentException(
"Expected dimension " + expectedDimension +
" but got " + dimension
);
}
store.add(embedding);
}
}try {
// Invalid: comparison operator on string
Filter filter = metadataKey("name").isGreaterThan("M");
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.filter(filter)
.build();
store.search(request);
} catch (RuntimeException e) {
System.err.println("Invalid filter: " + e.getMessage());
// Action: Use isEqualTo or isIn for string values
}Prevention:
// For strings, use equality or collection filters
Filter validFilter = metadataKey("name").isEqualTo("Smith");
Filter validFilter2 = metadataKey("name").isIn(names);
// For numbers, comparison operators work
Filter numericFilter = metadataKey("year").isGreaterThan(2020);try {
store.search(request);
} catch (RuntimeException e) {
String message = e.getMessage().toLowerCase();
if (message.contains("collection")) {
System.err.println("Collection error: " + e.getMessage());
// Collection may have been deleted or corrupted
} else if (message.contains("404") || message.contains("not found")) {
System.err.println("Resource not found: " + e.getMessage());
} else if (message.contains("500") || message.contains("internal server")) {
System.err.println("Chroma server error: " + e.getMessage());
// Check Chroma server logs
} else {
System.err.println("Unknown error: " + e.getMessage());
}
}public class BatchProcessor {
public List<String> addAllWithErrorHandling(
List<Embedding> embeddings,
List<TextSegment> segments
) {
try {
return store.addAll(embeddings, segments);
} catch (Exception e) {
System.err.println("Batch add failed: " + e.getMessage());
// Fallback: add individually to identify failures
List<String> ids = new ArrayList<>();
for (int i = 0; i < embeddings.size(); i++) {
try {
String id = store.add(embeddings.get(i), segments.get(i));
ids.add(id);
} catch (Exception itemError) {
System.err.println("Failed item " + i + ": " +
itemError.getMessage());
ids.add(null); // Mark failure
}
}
return ids;
}
}
}public void addAllInChunks(
List<Embedding> embeddings,
List<TextSegment> segments,
int chunkSize
) {
for (int i = 0; i < embeddings.size(); i += chunkSize) {
int end = Math.min(i + chunkSize, embeddings.size());
try {
List<Embedding> embBatch = embeddings.subList(i, end);
List<TextSegment> segBatch = segments.subList(i, end);
store.addAll(embBatch, segBatch);
System.out.println("Processed chunk " + (i / chunkSize + 1));
} catch (Exception e) {
System.err.println("Chunk " + (i / chunkSize + 1) +
" failed: " + e.getMessage());
// Continue with next chunk or handle failure
}
}
}public class MonitoredStore {
private final ChromaEmbeddingStore store;
private final Logger logger;
public String add(Embedding embedding, TextSegment segment) {
long startTime = System.currentTimeMillis();
try {
String id = store.add(embedding, segment);
long duration = System.currentTimeMillis() - startTime;
logger.info("Add successful - duration: {}ms", duration);
return id;
} catch (java.net.http.HttpTimeoutException e) {
long duration = System.currentTimeMillis() - startTime;
logger.error("Add timeout after {}ms: {}", duration, e.getMessage());
throw e;
} catch (Exception e) {
logger.error("Add failed: {}", e.getMessage(), e);
throw e;
}
}
}public class MetricsStore {
private final AtomicLong successCount = new AtomicLong();
private final AtomicLong failureCount = new AtomicLong();
private final AtomicLong totalDuration = new AtomicLong();
public String addWithMetrics(Embedding embedding, TextSegment segment) {
long start = System.currentTimeMillis();
try {
String id = store.add(embedding, segment);
successCount.incrementAndGet();
totalDuration.addAndGet(System.currentTimeMillis() - start);
return id;
} catch (Exception e) {
failureCount.incrementAndGet();
throw e;
}
}
public void printMetrics() {
long success = successCount.get();
long failure = failureCount.get();
long total = success + failure;
long avgDuration = total > 0 ? totalDuration.get() / success : 0;
System.out.println("Success: " + success);
System.out.println("Failure: " + failure);
System.out.println("Success rate: " +
(total > 0 ? (success * 100.0 / total) : 0) + "%");
System.out.println("Avg duration: " + avgDuration + "ms");
}
}@Test
public void testConnectionError() {
// Use invalid URL to test connection error handling
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://invalid-host:9999")
.timeout(Duration.ofSeconds(1))
.build();
assertThrows(Exception.class, () -> {
store.add(Embedding.from(new float[]{1.0f, 0.0f, 0.0f}));
});
}
@Test
public void testTimeoutError() {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://localhost:8000")
.timeout(Duration.ofMillis(1)) // Very short timeout
.build();
// May timeout with large operations
List<Embedding> largeList = generateLargeEmbeddingList();
assertThrows(java.net.http.HttpTimeoutException.class, () -> {
store.addAll(largeList);
});
}Install with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-chroma