Skip to content

Improve error handling for invalid index names with helpful suggestions #16

@simianhacker

Description

@simianhacker

Problem

When a user provides an invalid index name (either through the index parameter in tools or via the ELASTICSEARCH_INDEX environment variable), they receive a raw Elasticsearch error that isn't helpful:

index_not_found_exception: no such index [sematic-code-search-mcp-server-repo]

This error doesn't guide the user toward a solution. A common issue is typos in index names (e.g., "sematic" instead of "semantic").

Proposed Solution

Instead of allowing the raw Elasticsearch error to bubble up, catch index_not_found_exception errors and provide a helpful response that:

  1. Clearly states the index wasn't found
  2. Automatically lists all available indices (using the existing list_indices functionality)
  3. Optionally: Suggests similar index names if there's a close match (fuzzy matching)

Example Improved Error Message

The index 'sematic-code-search-mcp-server-repo' was not found.

Available indices:
- semantic-code-search-mcp-server-repo (159 files)
- semantic-code-search-indexer-repo (81 files)
- kibana-repo (70,870 files)
- elasticsearch-repo (28,243 files)
- grafana-repo (14,506 files)
- beats-repo (10,458 files)
- eui-repo (3,109 files)

Did you mean 'semantic-code-search-mcp-server-repo'?

Implementation Context

Where to Add Error Handling

The error handling should be added as a centralized wrapper around Elasticsearch queries. All tools that accept an index parameter eventually call client.search() from src/utils/elasticsearch.ts.

Key locations:

  1. src/utils/elasticsearch.ts - The client object is exported from here. Consider creating a wrapper function like:
export async function searchWithErrorHandling(searchParams: any) {
  try {
    return await client.search(searchParams);
  } catch (error) {
    if (error.meta?.body?.error?.type === 'index_not_found_exception') {
      // Return helpful error with available indices
      const indicesInfo = await listIndices();
      return {
        error: true,
        message: `The index '${searchParams.index}' was not found.\n\nAvailable indices:\n${indicesInfo}`,
      };
    }
    throw error;
  }
}
  1. Individual tools - Each tool that uses an index parameter would need to check for this error response and format it appropriately for CallToolResult.

Tools That Accept Index Parameter

These tools all accept an optional index parameter and would benefit from this improvement:

  • semantic_code_search (src/mcp_server/tools/semantic_code_search.ts)
  • map_symbols_by_query (src/mcp_server/tools/list_symbols_by_query.ts)
  • symbol_analysis (src/mcp_server/tools/symbol_analysis.ts)
  • read_file_from_chunks (src/mcp_server/tools/read_file.ts)
  • document_symbols (src/mcp_server/tools/document_symbols.ts)
  • discover_directories (if it exists)

Reusing Existing Functionality

The list_indices tool already exists (src/mcp_server/tools/list_indices.ts) and can be reused to get the formatted list of available indices. Consider:

  1. Extracting the core logic from listIndices() into a shared utility function
  2. Having both the tool and the error handler call this shared function
  3. The shared function should return a formatted string showing available indices

Optional: Fuzzy Matching

For an even better UX, consider using a string similarity algorithm (like Levenshtein distance) to suggest the closest matching index name. Libraries like string-similarity or fuzzysort could help:

import stringSimilarity from 'string-similarity';

function findClosestIndex(requestedIndex: string, availableIndices: string[]): string | null {
  const matches = stringSimilarity.findBestMatch(requestedIndex, availableIndices);
  if (matches.bestMatch.rating > 0.6) { // 60% similarity threshold
    return matches.bestMatch.target;
  }
  return null;
}

Implementation Steps

  1. Create a shared utility function in src/utils/elasticsearch.ts that formats available indices
  2. Create a wrapper for client.search() that catches index_not_found_exception
  3. When caught, call the shared formatting function and return a helpful error
  4. Update each tool to use the wrapper instead of direct client.search() calls
  5. Ensure the error response conforms to the CallToolResult type
  6. (Optional) Add fuzzy matching for "Did you mean...?" suggestions
  7. Add tests for the error handling

Testing

After implementation, test with:

// Test with typo
{ "index": "sematic-code-search-mcp-server-repo", "query": "test" }

// Test with completely wrong index
{ "index": "nonexistent-index", "query": "test" }

// Test with no index (should use default from env)
{ "query": "test" }

User Experience Impact

This change significantly improves the developer experience by:

  • Reducing confusion when typos occur
  • Making the available indices immediately visible
  • Providing actionable information rather than a cryptic error
  • Helping users discover what indices are available without knowing to call list_indices

Additional Notes

  • The error should be returned as a normal response, not thrown, so the MCP protocol doesn't see it as a server error
  • Consider logging the original Elasticsearch error for debugging purposes
  • This pattern could be extended to other common Elasticsearch errors (authentication, connection issues, etc.)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions