Skip to content

impact command crashes with SIGSEGV on arm64 macOS due to concurrent kuzu queries #292

@Moomak

Description

@Moomak

Environment

  • gitnexus 1.4.1, kuzu 0.11.3
  • Node.js v24.12.0, arm64 darwin (Apple Silicon)
  • Indexed repos: 3 repos, largest = ~40k nodes / ~110k edges

Problem

gitnexus impact consistently crashes with exit code 139 (SIGSEGV) while context, cypher, and list work fine.

Root Cause

The impact() method in local-backend.js (line ~1257) runs 3 enrichment queries via Promise.all:

  • STEP_IN_PROCESS query
  • MEMBER_OF (all impacted) query
  • MEMBER_OF (depth-1 only) query

All 3 run concurrently against the same kuzu connection pool with large IN [...] clauses (50+ long ID strings). This triggers a native crash in kuzu's embedded engine on arm64 macOS.

Reproduction

gitnexus analyze /path/to/large-repo   # ~40k+ nodes
gitnexus impact "anyMethod" -r my-repo -d upstream --depth 2
# → exit code 139 (SIGSEGV)

Individual queries work fine:

gitnexus cypher "MATCH (caller)-[r:CodeRelation]->(n) WHERE n.id IN ['Method:src/Services/MyService.php:myMethod:102'] AND r.type IN ['CALLS'] RETURN caller.name" -r my-repo
# → works, returns results

context also works (returns 30+ callers for the same symbol that crashes impact).

Workaround

In dist/mcp/local/local-backend.js, change enrichment from Promise.all to sequential await and cap the IN-clause to 100 IDs:

// Before (crashes)
const [processRows, moduleRows, directModuleRows] = await Promise.all([
    executeQuery(repo.id, `...WHERE s.id IN [${allIds}]...`).catch(() => []),
    executeQuery(repo.id, `...WHERE s.id IN [${allIds}]...`).catch(() => []),
    d1Ids ? executeQuery(repo.id, `...WHERE s.id IN [${d1Ids}]...`).catch(() => []) : Promise.resolve([]),
]);

// After (works)
const cappedImpacted = impacted.slice(0, 100);
const allIds = cappedImpacted.map(i => `'${i.id.replace(/'/g, "''")}'`).join(', ');
const processRows = await executeQuery(repo.id, `...`).catch(() => []);
const moduleRows = await executeQuery(repo.id, `...`).catch(() => []);
const directModuleRows = d1Ids ? await executeQuery(repo.id, `...`).catch(() => []) : [];

Also raised QUERY_TIMEOUT_MS from 30s → 120s in kuzu-adapter.js — the default 30s can be tight for large repos, and when it fires inside MCP stdio mode the connection just drops silently.

Additional Finding

impact at class level (e.g., impact "MyService") returns 0 results because CALLS edges in the graph are method-to-method, not class-to-class. Using method names (e.g., impact "myMethod") works correctly. This might be worth documenting or auto-aggregating method-level edges to the parent class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions