Skip to content

fix: resolve Cannot find module @altimateai/altimate-core on npm install#259

Merged
anandgupta42 merged 2 commits intomainfrom
fix/altimate-core-module-not-found
Mar 18, 2026
Merged

fix: resolve Cannot find module @altimateai/altimate-core on npm install#259
anandgupta42 merged 2 commits intomainfrom
fix/altimate-core-module-not-found

Conversation

@anandgupta42
Copy link
Contributor

What does this PR do?

Fixes npm install -g altimate-code producing Cannot find module '@altimateai/altimate-core' (and a hidden @altimateai/dbt-integration error behind it).

Three root causes:

  1. @altimateai/altimate-core is a NAPI-RS native module — Bun's bundler inlines the JS loader but cannot embed .node native binaries. The published wrapper package didn't declare it as a dependency, so it was never installed.

  2. @altimateai/dbt-integration and yaml were marked as external, but without code splitting Bun inlines dynamic import() targets into the main chunk — external require() fails at startup before any try/catch can catch it.

  3. Bun compiled binaries resolve externals from /$bunfs/root/ (virtual FS), not the physical binary location — standard node_modules resolution doesn't work.

Fixes:

  • bin/altimate, bin/altimate-code: Set NODE_PATH to the nearest node_modules before spawning the binary
  • script/build.ts: Add @altimateai/altimate-core to externals (NAPI can't be embedded); remove dbt-integration and yaml from externals (bundle them — external packages crash at startup without code splitting)
  • script/publish.ts: Add @altimateai/altimate-core as a dependencies entry in both scoped and unscoped wrapper packages

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Issue for this PR

Closes #258

How did you verify your code works?

  1. Built locally with bun run script/build.ts --single
  2. Simulated npm install layout in /tmp/test-altimate-e2e2/ with altimate-core installed as a dependency
  3. Verified node bin/altimate-code --version prints version successfully
  4. Verified node bin/altimate-code --help shows full CLI help
  5. Confirmed NODE_PATH works: tested binary with NODE_PATH pointing to node_modules — altimate-core resolves correctly
  6. Ran full test suite: 3295 pass, 0 fail
  7. Typecheck passes on push

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have verified the fix works end-to-end

🤖 Generated with Claude Code

…install

Three issues prevented `npm install -g altimate-code` from working:

1. `@altimateai/altimate-core` (NAPI-RS native module) cannot be embedded
   in Bun single-file executables — mark it as external and add it as a
   dependency in the published wrapper packages so npm installs it.

2. `@altimateai/dbt-integration` and `yaml` were external but without code
   splitting, Bun inlines dynamic `import()` targets into the main chunk —
   external `require()` fails at startup. Remove them from externals so they
   get bundled.

3. Bun compiled binaries resolve externals from `/$bunfs/root/` (virtual FS),
   not the physical binary location. The bin wrapper now sets `NODE_PATH` to
   the nearest `node_modules` so the binary can find external packages.

Closes #258

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Copy link
Contributor Author

@anandgupta42 anandgupta42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-review self-commentary on key design decisions. See inline comments below.

current = parent
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why NODE_PATH?

Bun compiled binaries resolve external require() calls from /$bunfs/root/ — a virtual filesystem with no node_modules. Standard Node resolution (walking up parent dirs from the binary's physical location) doesn't apply.

NODE_PATH is the only mechanism that works across all Bun versions to inject additional module search paths into a compiled binary. Tested and confirmed working with Bun 1.3.10.

Alternative considered: shipping altimate-core alongside the binary in the platform package — rejected because it would require cross-compiling the NAPI addon per-platform in our CI, which the altimate-core repo already handles via its own release pipeline.

// at runtime. Bun compiled binaries resolve externals via standard Node
// resolution from the binary's location, walking up to the wrapper
// package's node_modules.
//
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key insight: external ≠ lazy without code splitting.

Bun's --compile without splitting: true inlines all modules (including dynamic import() targets) into a single chunk. Any external package referenced transitively from a dynamic import will emit a top-level require() that runs at startup — before the try/catch around the import() can catch it.

This is why @altimateai/dbt-integration and yaml were crashing the binary at startup even though they were only referenced inside lazy import() calls wrapped in try/catch.

Rule of thumb for this build config: Only mark packages as external if they truly cannot be bundled (native addons like NAPI .node files or database drivers).

// dbt integration — heavy transitive deps, loaded on first dbt operation
"@altimateai/dbt-integration",
// Database drivers — users install on demand per warehouse
// NAPI native module — cannot be embedded in Bun single-file executable.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why altimate-core must be external (not bundled):

@altimateai/altimate-core is a NAPI-RS package. Its index.js is a dynamic loader that does conditional require() to find platform-specific .node binaries (e.g. @altimateai/altimate-core-darwin-arm64). Bun's docs confirm you can embed .node files with direct require('./addon.node'), but the NAPI-RS auto-generated loader uses dynamic platform detection that Bun's bundler can't statically analyze.

So the JS loader gets inlined but the native binary doesn't → runtime crash. Making it external + installing via npm deps is the correct approach.

// These cannot be embedded in Bun's single-file executable — the JS loader
// dynamically require()s platform-specific .node binaries at runtime.
const runtimeDependencies: Record<string, string> = {
"@altimateai/altimate-core": pkg.dependencies["@altimateai/altimate-core"],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version pinning: This reads the version range from packages/opencode/package.json ("^0.2.3"), ensuring the published wrapper always matches what was tested at build time. If altimate-core gets a new release, it's automatically picked up within the semver range on next npm install.

Using dependencies (not optionalDependencies) because altimate-core is mandatory — the CLI cannot function without it (all 34 native SQL analysis methods depend on it).

// Resolve NODE_PATH so the compiled Bun binary can find external packages
// installed alongside the wrapper (e.g. @altimateai/altimate-core NAPI module).
const env = { ...process.env }
const targetDir = path.dirname(path.dirname(fs.realpathSync(target)))

This comment was marked as outdated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in commit c7e41b4fs.realpathSync(target) is now wrapped in a try-catch block. If the path doesn't exist, we fall through gracefully and let spawnSync report the error via result.error.

…ath NODE_PATH, validation

Fixes from 6-model consensus code review:

1. Wrap `fs.realpathSync(target)` in try-catch — previously would crash
   with a stack trace if `ALTIMATE_CODE_BIN_PATH` pointed to a missing
   file. Now falls back gracefully to `spawnSync` error handling.
   (Flagged by 4/6 models)

2. Collect ALL `node_modules` paths walking upward (not just first found)
   and search from BOTH the binary dir AND the wrapper script dir. This
   handles pnpm strict layouts, hoisted monorepos, and npm flat installs.
   (Suggested by Gemini 3.1 Pro)

3. Move `scriptDir` initialization before `run()` to avoid ReferenceError
   when `ALTIMATE_CODE_BIN_PATH` is set (calls `run()` before `scriptDir`
   was previously defined).
   (Flagged by Gemini 3.1 Pro)

4. Add fail-fast validation for `@altimateai/altimate-core` dependency in
   `publish.ts` — prevents silent `undefined` if accidentally removed
   from `package.json`.
   (Flagged by Kimi K2.5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@anandgupta42
Copy link
Contributor Author

Review findings addressed in c7e41b4

A 6-model consensus code review (Claude, GPT 5.2 Codex, Gemini 3.1 Pro, Kimi K2.5, MiniMax M2.5, GLM-5) identified 4 actionable issues. All have been fixed:

Fix Source Commit
fs.realpathSync wrapped in try-catch (was crashing on invalid paths) 4/6 models consensus c7e41b4
Collect ALL node_modules paths + search from both script dir and binary dir (handles pnpm, hoisted monorepos) Gemini 3.1 Pro c7e41b4
Move scriptDir init before run() (avoids ReferenceError with ALTIMATE_CODE_BIN_PATH) Gemini 3.1 Pro c7e41b4
Fail-fast validation for @altimateai/altimate-core dep in publish.ts Kimi K2.5 c7e41b4

Note: The inline pre-review comments from the first commit (35230ec) reference the old code and are now superseded by the fixes above. The Sentry bot finding (realpathSync crash) is also resolved.

@anandgupta42 anandgupta42 merged commit 058c23e into main Mar 18, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: npm install -g altimate-code fails with Cannot find module '@altimateai/altimate-core'

1 participant