Skip to content

Bug: VersionManager generates invalid Cypher WHERE () AND ... on Neptune Database #408

Description

@evanerwee

GitHub Issue: awslabs/graphrag-toolkit

Title

Bug: VersionManager generates invalid Cypher WHERE () AND ... on Neptune Database

Labels

bug

Body

Description

When using LexicalGraphIndex.extract_and_build(nodes, enable_versioning=True) with Neptune Database, the VersionManager._get_existing_source_nodes() method generates syntactically invalid Cypher that Neptune rejects.

Error

MalformedQueryException: Invalid input 'A': expected whitespace, comment 
or a relationship pattern (line 4, column 18 (offset: 127))
[query_ref: e809b/*, query: // find source nodes to be versioned, parameters: **REDACTED**]

Root Cause

In version_manager.py, when other_filter_criteria is an empty dict (which occurs when nodes don't yet have nested source.metadata structure during the first build phase):

  1. to_metadata_filter({}) creates MetadataFilters(filters=[])
  2. parse_metadata_filters_recursive(MetadataFilters(filters=[])) joins an empty list and returns "()" (empty parentheses)
  3. The guard if not where_clauses: return [] at line 70 does NOT catch this because "()" is a truthy 2-character string
  4. The generated query becomes: WHERE () AND coalesce(source.__aws__versioning__id_fields__, ...) = $param
  5. Neptune rejects WHERE () AND ... as syntactically invalid

Relevant code in graph_utils.py:parse_metadata_filters_recursive:

condition = f' {metadata_filters.condition.value.upper()} '
return f"({condition.join(filter_strs)})"  # Returns "()" when filter_strs is []

Confirmed by Direct Neptune Testing

Ran isolated query tests against Neptune Database 1.4.7.0:

Test Query Pattern Result
Map literal in RETURN RETURN {id: id(n)} AS result ✅ Works
__aws__ property names t.__aws__versioning__id_fields__ ✅ Works
coalesce on versioning properties coalesce(t.__aws__versioning__valid_from__, -1) ✅ Works
WHERE () AND filter WHERE () AND id(n) IS NOT NULL ❌ MalformedQueryException
Full versioning query (properly formed WHERE) Complete pattern ✅ Works

All Cypher features used by the versioning system work on Neptune. The ONLY issue is the empty WHERE () clause.

Proposed Fix

Either:

Option A — Fix the guard in version_manager.py:70:

if not where_clauses or where_clauses.strip() in ('', '()'):
    return []

Option B — Fix parse_metadata_filters_recursive in graph_utils.py to return '' for empty filter lists:

if not filter_strs:
    return ''

Reproduction Steps

  1. Create TextNodes with flat metadata (e.g., {"page_id": "123", "space_key": "SD"})
  2. Call add_versioning_info(metadata, id_fields=["page_id", "space_key"])
  3. Call LexicalGraphIndex.extract_and_build(nodes, enable_versioning=True) against Neptune Database
  4. The extraction phase restructures metadata, but during certain code paths (first-time ingest, partial extraction), the source.metadata dict lookup returns empty
  5. VersionManager generates invalid WHERE () AND ... query

Environment

  • Neptune Database: 1.4.7.0 (latest, Serverless)
  • graphrag-lexical-graph: 3.18.6
  • OpenSearch Serverless (AOSS)
  • Region: us-east-1

Workaround

Disable versioning (enable_versioning=False). First-time ingest works correctly. For re-ingestion, call delete_sources() before re-ingesting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions