spring-projects/spring-ai · error · RuntimeException

Failed to add document to index

Error message

Failed to add document to index

What it means

SessionIndex.add() adds a tool document to the session's Lucene index via indexTool/indexTools. If the write throws an IOException it is wrapped in this RuntimeException. AlreadyClosedException is intentionally swallowed with a warning (index concurrently cleared), so this error represents a genuine IO write failure, not concurrent clearing.

Source

Thrown at spring-ai-tool-search-tool/src/main/java/org/springframework/ai/tool/toolsearch/index/lucene/LuceneToolIndex.java:193

	 * document is silently dropped (the session was cleared anyway).
	 * @param sessionId the session ID associated with the tool
	 * @param id unique identifier for the tool
	 * @param toolName name of the tool
	 * @param toolDescription description of the tool (searchable)
	 */
	public void add(String sessionId, String id, String toolName, String toolDescription) {
		try {
			SessionIndex sessionIndex = getOrCreateSessionIndex(sessionId);
			Document doc = this.createDocument(sessionId, id, toolName, toolDescription);
			sessionIndex.writer.addDocument(doc);
		}
		catch (AlreadyClosedException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Skipping add for session '" + sessionId + "': index was concurrently cleared");
			}
		}
		catch (IOException e) {
			throw new RuntimeException("Failed to add document to index", e);
		}
	}

	/**
	 * Commits all pending changes to all session indexes. Call this after batch additions
	 * for better performance.
	 */
	public void commit() {
		for (Map.Entry<String, SessionIndex> entry : this.sessionIndexes.entrySet()) {
			try {
				SessionIndex sessionIndex = entry.getValue();
				sessionIndex.writer.commit();
				sessionIndex.refreshReader();
			}
			catch (IOException e) {
				throw new RuntimeException("Failed to commit changes to index for session: " + entry.getKey(), e);
			}
		}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Check the wrapped IOException cause; fix the root IO condition (disk space, permissions, file descriptors).
  2. Raise the open-file ulimit if 'Too many open files' appears; session indexes each hold Lucene resources.
  3. Call commit() (or commitAll) after batch additions and ensure clearIndex/index operations are not racing.
  4. If the index is corrupted, clear and rebuild it by re-indexing the session's tools.

Example fix

// before
for (ToolReference t : tools) { index.indexTool(sessionId, t); } // many session indexes open, fd exhaustion
// after
index.indexTools(sessionId, tools); // batch API
index.commitAll();
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check filesystem capacity before bulk indexing
if (dir.getUsableSpace() < MIN_FREE_BYTES) {
    throw new IllegalStateException("Insufficient disk space for tool index");
}

Try / catch

try {
    toolIndex.indexTool(sessionId, toolReference);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().equals("Failed to add document to index")) {
        logger.error("Lucene write failed: {}", e.getCause(), e);
        toolIndex.clearIndex(sessionId);
        // re-index session tools after rebuild
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling indexTool(sessionId, toolReference) or indexTools(...) when the Lucene writer hits an IOException: disk full, closed directory/channel, lock acquisition failure, or corrupted index state.

Common situations: Disk exhaustion on the index volume, writing after the backing directory was deleted externally, too many open files (ulimit) exhausting file descriptors, or index corruption after a crash.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/fa4c169b5df29b25. Report an issue: GitHub.