Skip to content

import edges silently dropped on Next.js codebase — short IDs vs full-path node IDs (regression of #256) #1529

Closed

Description

@FahadBinHussain

i'm hitting the same class of bug as #256 on v0.9.1 — all import edges are silently dropped because the edge target IDs don't match the file node IDs.

repro

  • 216-code-file Next.js/TypeScript codebase (app router, app/, components/, lib/, prisma/, scripts/)
  • graphify . with node_modules excluded via extra_excludes
  • ast extraction produces 168 nodes and 260 edges
  • after build_from_json(): 168 nodes, 0 edges — every single edge dropped

root cause (same as #256)

edge targets use short names from import specifiers:

{"source": "app_about_page_ts", "target": "about_page", "relation": "imports_from"}
{"source": "app_admin_articles_new_newarticleclient_ts", "target": "components_languageprovider_uselanguage", "relation": "imports_from"}

but file node IDs use full paths:

{"id": "app_about_page_ts"}
{"id": "components_languageprovider_uselanguage_ts"}

about_page doesn't match app_about_page_ts. components_languageprovider_uselanguage doesn't match components_languageprovider_uselanguage_ts. so build_from_json drops all 260 edges as "external/stdlib".

the v0.4.3 fix resolved relative imports (./foo.js → full path), but these edge targets look like they're generated from import specifier stems without resolving to the full filesystem path. possibly bare imports or next.js alias patterns (@/components/...).

what i tried

  • v0.8.51 → same issue
  • upgraded to v0.9.1 → same issue
  • post-build fuzzy match workaround (stem matching) recovered 110/260 edges

environment

  • graphifyy 0.9.1
  • windows 11
  • next.js 15, typescript 5.9
  • python 3.13 (uv tool install)

Activity

  1. safishamsi commented on Jun 29, 2026

    @safishamsi
    Member

    Confirmed and fixed on v8 (2133539). You were exactly right that it's a short-ID vs full-path-ID mismatch, and it was a regression from the 0.9.0 full-repo-relative node-ID migration.

    Root cause: relative imports resolve to repo-relative paths and match definition node IDs fine, but tsconfig path-alias and workspace-package imports resolve to absolute paths (their bases get .resolve()d), so the import-target ID baked in the on-disk prefix and never matched the repo-relative definition node — the edge was dropped at build. The id-remap post-pass now also registers the absolute-resolved form of each input path (file-level imports_from edges) and both prefix forms for named-import symbol edges, so alias/workspace import targets remap to the canonical ID.

    Verified end-to-end on a Next.js-style @/-alias project with relative input paths: the built graph now has the imports_from, named-imports, and calls edges all landing on real nodes, with zero orphan nodes or dangling edges. Added regression tests (the key one drives extract() with relative input paths, which is what reproduces the bug — the existing alias tests passed only because pytest's tmp_path is pre-resolved). Ships in the next release.

  2. added a commit that references this issue on Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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