stablyai/orca · critical

Packaged main bundle has bare runtime imports without copied

Error message

Packaged main bundle has bare runtime imports without copied node_modules: ${[...missing].join(', ')}

What it means

The `verifyPackagedMainRuntimeDeps` function scans the source of the packaged main bundle files for `require("...")` calls with bare specifiers (non-relative, non-electron, non-builtin). For each, it checks if the package exists at `resources/node_modules/packageName`. If any are missing, this error lists them. This catches the case where a new runtime dependency was added to the main bundle but wasn't included in the packaged node_modules copy.

Source

Thrown at config/packaged-runtime-node-modules.cjs:248

    // Why: @electron/asar lists entries with host separators; Windows returns
    // backslashes, and extractFile expects that same host-style path.
    const internalPath = entry.replace(/^[\\/]+/, '')
    const source = asar.extractFile(asarPath, internalPath).toString('utf8')
    for (const match of source.matchAll(/require\(["']([^"']+)["']\)/g)) {
      const specifier = match[1]
      if (!isPackagedExternalSpecifier(specifier)) {
        continue
      }
      const packageName = packageNameFromSpecifier(specifier)
      if (!existsSync(join(resourcesDir, 'node_modules', ...packageName.split('/')))) {
        missing.add(packageName)
      }
    }
  }

  if (missing.size > 0) {
    throw new Error(
      `Packaged main bundle has bare runtime imports without copied node_modules: ${[
        ...missing
      ].join(', ')}`
    )
  }
}

function normalizeNodePtyWindowsArch(electronArch) {
  const architecture = normalizeElectronArchitecture(electronArch)
  if (architecture !== 'x64' && architecture !== 'arm64') {
    throw new Error(`Unsupported packaged node-pty Windows architecture: ${architecture}`)
  }
  return architecture
}

function normalizeElectronArchitecture(electronArch) {
  const architecture =
    typeof electronArch === 'number'

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Read the error — it lists the exact missing package names. For each, add it to PACKAGED_RUNTIME_PACKAGE_ROOTS in packaged-runtime-node-modules.cjs:16.
  2. If the package should be bundled instead of external (no runtime require), add it to BUNDLED_MAIN_DEPENDENCIES in electron.vite.config.ts so Rollup inlines it.
  3. Verify the package is installed: `ls node_modules/missing-package-name`.
  4. For scoped packages, ensure the full scope/name is in the roots list.

Example fix

// before — main bundle requires a new package
const { parse } = require('new-parser')

// after — add to PACKAGED_RUNTIME_PACKAGE_ROOTS
const PACKAGED_RUNTIME_PACKAGE_ROOTS = [
  // ...existing...
  'new-parser'
]
Defensive patterns

Strategy: validation

Validate before calling

// Scan main bundle source for bare requires and check node_modules coverage
import { readFileSync, existsSync, readdirSync } from 'fs'
import { join } from 'path'
function verifyRuntimeDepsCovered(mainBundlePath, resourcesDir) {
  const source = readFileSync(mainBundlePath, 'utf8')
  const requires = [...source.matchAll(/require\(["']([^"']+)["']\)/g)].map(m => m[1])
  const bare = requires.filter(s => !s.startsWith('.') && s !== 'electron')
  const missing = bare.filter(s => {
    const pkg = s.startsWith('@') ? s.split('/').slice(0, 2).join('/') : s.split('/')[0]
    return !existsSync(join(resourcesDir, 'node_modules', pkg))
  })
  if (missing.length) throw new Error(`Missing node_modules for: ${missing.join(', ')}`)
}

Prevention

When it happens

Trigger: Adding a `require('new-package')` to the main bundle source (src/main/index.ts or agent-hooks) without adding 'new-package' to PACKAGED_RUNTIME_PACKAGE_ROOTS in packaged-runtime-node-modules.cjs. A dependency that was previously bundled (in BUNDLED_MAIN_DEPENDENCIES) being moved to external, making it a bare require that needs packaged node_modules.

Common situations: Importing a new npm package in main process code without updating the packaging config. Changing the externalizeDeps configuration so a previously-bundled dependency becomes external. Adding a require() for a scoped package (@scope/name) — the packageNameFromSpecifier function handles this, but the package must still be in the roots.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/1370fc8204a760d4. Report an issue: GitHub.