Skip to content

fix: mergeGraph UUID remap doesn't cover Type/Class nodes — causes dangling edges #107

@jonathanpopham

Description

@jonathanpopham

Problem

The daemon's mergeGraph in internal/files/daemon.go remaps old→new UUIDs for File and Function nodes when a file is re-processed incrementally. But it does not remap Type or Class nodes. When the API returns new UUIDs for these node types, existing relationships from unchanged files still point at the old IDs, creating dangling edges.

Repro

  1. Full generate on Next.js (~12,000 nodes)
  2. Incremental update for 3 files including packages/next/src/shared/lib/constants.ts
  3. Merge the incremental result into the baseline
  4. Check for dangling edges:
DANGLING: type=imports, endNode c100dae7:51fd:fce5:81c8:9976494ceb39
  Missing node was: labels=['Type'], filePath=constants.ts, name=CompilerNameValues

A Type node (CompilerNameValues) from constants.ts got a new UUID in the incremental response. An imports relationship from an unchanged file still references the old UUID. The merge kept the old relationship but didn't remap the endpoint.

Root cause

daemon.go lines ~380-410 build the old→new remap only for File and Function nodes:

if n.HasLabel("File") {
    if newID, ok := incFileByPath[fp]; ok && newID != n.ID {
        oldToNew[n.ID] = newID
    }
} else if n.HasLabel("Function") {
    // ...remap by filePath:name...
}

Type and Class nodes are not remapped.

Fix

Extend the remap to cover Type and Class nodes using the same filePath:name key pattern:

} else if n.HasLabel("Type") || n.HasLabel("Class") {
    name := n.Prop("name")
    key := fp + ":" + name
    if newID, ok := incTypeByKey[key]; ok && newID != n.ID {
        oldToNew[n.ID] = newID
    }
}

This requires building incTypeByKey and incClassByKey maps from the incremental response, same as incFnByKey.

Impact

Low — affects relationships pointing at Type/Class nodes in changed files. Most relationships point at File or Function nodes which are already remapped. Found 1 dangling edge in a 27,000-relationship graph (0.004%). But it's a correctness issue that will compound with more incremental updates.

Pre-existing in both the CLI (internal/files/daemon.go) and graph-fusion (internal/daemon/daemon.go).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions