stablyai/orca · error

package.json must declare bin.orca

Error message

package.json must declare bin.orca

What it means

verifyPackageCliBin reads projectDir/package.json and requires a non-empty string at bin.orca — the published CLI entrypoint. The package boundary check (CommonJS out/package.json downstream) and the executable-bit check both depend on resolving this bin target first, so a missing declaration aborts before any filesystem work. The message is fixed (no interpolation) because the defect is in the manifest, not a path.

Source

Thrown at config/scripts/verify-cli-bin.mjs:32

  null,
  2
)}\n`

/**
 * Verifies the published CLI entrypoint and the module-type boundary for the
 * compiled output tree that the packaged CLI loads at runtime.
 */
export function verifyPackageCliBin({
  projectDir = path.resolve(import.meta.dirname, '..', '..'),
  fixExecutable = false,
  fixPackageJson = false,
  runHelp = false
} = {}) {
  const packageJsonPath = path.join(projectDir, 'package.json')
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
  const binTarget = packageJson.bin?.orca
  if (typeof binTarget !== 'string' || binTarget.length === 0) {
    throw new Error('package.json must declare bin.orca')
  }

  const binPath = path.resolve(projectDir, binTarget)
  const stats = statSync(binPath)
  if (!stats.isFile()) {
    throw new Error(`bin.orca target is not a file: ${binTarget}`)
  }
  if (stats.size === 0) {
    throw new Error(`bin.orca target is empty: ${binTarget}`)
  }

  const content = readFileSync(binPath, 'utf8')
  if (!content.startsWith('#!/usr/bin/env node\n')) {
    throw new Error(`bin.orca target must start with a Node shebang: ${binTarget}`)
  }

  const outPackageJsonPath = path.join(projectDir, 'out', 'package.json')
  if (fixPackageJson) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Add `"bin": { "orca": "<path-to-compiled-entry>" }` to package.json with the path resolved relative to projectDir.
  2. Ensure the path points at the built/compiled entry, not the TypeScript source.
  3. Re-run with no flags to confirm; the bin path must then exist, be non-empty, and carry the Node shebang.

Example fix

// before
{
  "name": "orca",
  "bin": {}
}
// after
{
  "name": "orca",
  "bin": { "orca": "out/cli/main.js" }
}
Defensive patterns

Strategy: validation

Validate before calling

const pkg = JSON.parse(readFileSync('package.json', 'utf8'))
if (typeof pkg.bin?.orca !== 'string' || pkg.bin.orca.length === 0) {
  throw new Error('package.json must declare a non-empty bin.orca before verify-cli-bin')
}

Type guard

function hasValidOrcaBin(pkg: unknown): pkg is { bin: { orca: string } } {
  return (
    typeof pkg === 'object' && pkg !== null &&
    'bin' in pkg && typeof (pkg as any).bin === 'object' &&
    typeof (pkg as any).bin?.orca === 'string' && (pkg as any).bin.orca.length > 0
  )
}

Prevention

When it happens

Trigger: Called via verifyPackageCliBin() when packageJson.bin?.orca is undefined, not a string, or an empty string at line 31. Reproduced by a package.json lacking a `bin` field, having `bin: {}`, or `bin: { orca: '' }`.

Common situations: Refactoring package.json and dropping the bin field; renaming the CLI from `orca` to something else without updating the verifier; a publish/release pipeline running verify-cli-bin on a package that was never wired as a CLI.

Related errors


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