Skip to content

Conversation

@donbr
Copy link

@donbr donbr commented Nov 24, 2025

Summary

Fixes the MCP server crash on startup when using Neo4j 5.x due to EquivalentSchemaRuleAlreadyExists error during index creation.

Problem

When build_indices_and_constraints() runs, it executes ~19 index creation queries in parallel via semaphore_gather(). Neo4j 5.x has a race condition where concurrent CREATE INDEX ... IF NOT EXISTS statements can fail even though the guard clause should prevent errors.

neo4j.exceptions.ClientError: {neo4j_code: Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists}
{message: An equivalent index already exists, 'Index( id=10, name='relation_uuid', type='RANGE', ...)'}

Solution

Wrap the build_indices_and_constraints() call in a try/except that catches this specific error and continues, since the indexes are successfully created by whichever parallel query completes first.

try:
    await self.client.build_indices_and_constraints()
except Exception as idx_error:
    if 'EquivalentSchemaRuleAlreadyExists' in str(idx_error):
        logger.warning(
            'Index creation race condition detected (Neo4j 5.x issue). '
            'Indexes likely already exist. Continuing...'
        )
    else:
        raise

Testing

  • Tested with Neo4j 5.26.0 and graphiti-core 0.24.1
  • Server initializes successfully with warning logged
  • All Graphiti operations (add_memory, search_nodes, etc.) work correctly
  • Indexes are properly created in Neo4j

Related Issues

Fixes #353

Checklist

  • Fix handles only the specific EquivalentSchemaRuleAlreadyExists error
  • Other exceptions are re-raised
  • Warning message logged for visibility
  • No impact on FalkorDB backend

Wrap build_indices_and_constraints() in try/except to catch
EquivalentSchemaRuleAlreadyExists error that occurs when Neo4j 5.x
processes parallel CREATE INDEX IF NOT EXISTS statements.

Fixes getzep#353
@danielchalef
Copy link
Member

danielchalef commented Nov 24, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@donbr
Copy link
Author

donbr commented Nov 24, 2025

I have read the CLA Document and I hereby sign the CLA

danielchalef added a commit that referenced this pull request Nov 24, 2025
@donbr
Copy link
Author

donbr commented Nov 24, 2025

TLDR Version: Neo4j 5.x Index Creation Race Condition

  • here's additional context in case different approaches want to be examined longer term. I went with what was simplest and least risky in the near term that allowed me to leverage the MCP functionality.

(thanks to the Graphiti team for all their hard work)

Summary

This PR fixes a race condition that causes the Graphiti MCP server to crash on startup when using Neo4j 5.x as the database backend. The issue occurs during index creation in build_indices_and_constraints().

Problem Description

Error Message

neo4j.exceptions.ClientError: {neo4j_code: Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists}
{message: An equivalent index already exists, 'Index( id=10, name='relation_uuid', type='RANGE',
schema=()-[:RELATES_TO {uuid}]-(), indexProvider='range-1.0' )'.}

Root Cause

  1. Parallel Index Creation: graphiti_core/driver/neo4j_driver.py runs all index creation queries in parallel via semaphore_gather() for performance
  2. Neo4j 5.x Race Condition: Neo4j 5.x has a known issue where concurrent CREATE INDEX ... IF NOT EXISTS statements can fail even though the IF NOT EXISTS clause should prevent errors
  3. MCP Server Crash: The MCP server wrapper doesn't handle this error, causing the entire server to fail initialization

Technical Details

The index creation code in graphiti_core/driver/neo4j_driver.py (lines 91-108):

async def build_indices_and_constraints(self, delete_existing: bool = False):
    # ... deletion logic ...

    await semaphore_gather(
        *[self.execute_query(query) for query in NEO4J_INDEX_QUERIES],
        *[self.execute_query(query) for query in NEO4J_CONSTRAINT_QUERIES],
    )

This executes ~19 index creation queries in parallel. When Neo4j 5.x processes these concurrently:

  • Multiple queries may try to create the same index simultaneously
  • Even with IF NOT EXISTS, Neo4j throws EquivalentSchemaRuleAlreadyExists
  • The first query that completes "wins", but others fail despite the guard clause

Affected Versions

  • Neo4j: 5.x (tested with 5.26.0)
  • graphiti-core: All versions up to 0.24.1
  • Not affected: FalkorDB backend (handles "already indexed" errors separately)

Solution

Wrap the build_indices_and_constraints() call in the MCP server with a try/except that catches this specific error and continues operation, since the indexes will have been created successfully by whichever parallel query completed first.

Code Change

File: mcp_server/src/graphiti_mcp_server.py (lines 281-292)

# Before:
await self.client.build_indices_and_constraints()

# After:
# Build indices - wrap in try/except to handle Neo4j 5.x race condition
# with parallel IF NOT EXISTS index creation
try:
    await self.client.build_indices_and_constraints()
except Exception as idx_error:
    if 'EquivalentSchemaRuleAlreadyExists' in str(idx_error):
        logger.warning(
            'Index creation race condition detected (Neo4j 5.x issue). '
            'Indexes likely already exist. Continuing...'
        )
    else:
        raise

Why This Fix Works

  1. Indexes are created: The parallel execution still creates all indexes - the error only occurs because some queries "see" indexes created by sibling queries
  2. Idempotent operation: Index creation is idempotent - if the index exists, the operation is a no-op
  3. Non-destructive: We only catch this specific error; other errors are re-raised
  4. Informative logging: Users see a warning explaining what happened

Testing

Before Fix

$ docker compose -f docker-compose-neo4j.yml up -d
$ docker logs docker-graphiti-mcp-1

# Output:
neo4j.exceptions.ClientError: {neo4j_code: Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists}
# Container exits with code 1

After Fix

$ docker compose -f docker-compose-neo4j.yml up -d
$ docker logs docker-graphiti-mcp-1

# Output:
2025-11-24 - graphiti_mcp_server - WARNING - Index creation race condition detected (Neo4j 5.x issue). Indexes likely already exist. Continuing...
2025-11-24 - graphiti_mcp_server - INFO - Successfully initialized Graphiti client

$ curl http://localhost:8000/health
{"status":"healthy","service":"graphiti-mcp"}

Verification

# Confirm indexes were created
$ docker exec docker-neo4j-1 cypher-shell -u neo4j -p demodemo "SHOW INDEXES" | wc -l
27  # All indexes present

# Confirm data operations work
$ curl -X POST http://localhost:8000/mcp -d '...'  # add_memory, search_nodes, etc.
# All operations successful

Related Issues

Alternative Solutions Considered

1. Sequential Index Creation

Approach: Modify neo4j_driver.py to run index queries sequentially instead of in parallel.

Pros: Eliminates race condition at source
Cons:

  • Slower startup (~19 queries × network latency)
  • Requires changes to graphiti-core
  • May impact other use cases that benefit from parallel execution

2. Add Retry Logic

Approach: Retry failed index creation queries individually.

Pros: More granular error handling
Cons:

  • Complex implementation
  • Still requires error handling in MCP server
  • Unnecessary since indexes are created by parallel queries

3. Pre-create Indexes via Script

Approach: Run index creation before starting the MCP server.

Pros: Separates concerns
Cons:

  • Requires additional setup step
  • Poor developer experience
  • Doesn't address the fundamental issue

Chosen Solution: Exception Handling in MCP Server

Rationale:

  • Minimal code change
  • Doesn't affect graphiti-core
  • Handles the specific failure mode gracefully
  • Maintains performance benefits of parallel execution
  • Clear logging for debugging

Checklist

  • Fix handles the specific EquivalentSchemaRuleAlreadyExists error
  • Other exceptions are re-raised (not silently swallowed)
  • Warning message is logged for visibility
  • Server initializes successfully after fix
  • All Graphiti operations work correctly (add_memory, search_nodes, etc.)
  • Indexes are properly created in Neo4j
  • No impact on FalkorDB backend

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The graphiti is not working propley with initial setup

2 participants