fix: Handle EquivalentSchemaRuleAlreadyExists errors in Neo4j driver

Fixes #1079

Neo4j 5.26+ throws EquivalentSchemaRuleAlreadyExists errors when
creating indices in parallel, even with IF NOT EXISTS clause.

This fix:
- Catches neo4j.exceptions.ClientError exceptions
- Checks for EquivalentSchemaRuleAlreadyExists error code
- Logs the occurrence as info instead of error
- Returns empty result to indicate success (index/constraint exists)

This prevents the MCP server from crashing on startup when multiple
CREATE INDEX IF NOT EXISTS queries run concurrently via semaphore_gather.

The solution follows the same pattern already implemented in the
FalkorDB driver for handling "already indexed" errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
supmo668 2025-11-23 19:21:55 -08:00
parent 582e093582
commit a65634c2e1

View file

@ -18,6 +18,7 @@ import logging
from collections.abc import Coroutine
from typing import Any
import neo4j.exceptions
from neo4j import AsyncGraphDatabase, EagerResult
from typing_extensions import LiteralString
@ -70,6 +71,15 @@ class Neo4jDriver(GraphDriver):
try:
result = await self.client.execute_query(cypher_query_, parameters_=params, **kwargs)
except neo4j.exceptions.ClientError as e:
# Handle race condition when creating indices/constraints in parallel
# Neo4j 5.26+ may throw EquivalentSchemaRuleAlreadyExists even with IF NOT EXISTS
if 'EquivalentSchemaRuleAlreadyExists' in str(e):
logger.info(f'Index or constraint already exists, continuing: {cypher_query_}')
# Return empty result to indicate success (index exists)
return EagerResult([], None, None) # type: ignore
logger.error(f'Error executing Neo4j query: {e}\n{cypher_query_}\n{params}')
raise
except Exception as e:
logger.error(f'Error executing Neo4j query: {e}\n{cypher_query_}\n{params}')
raise