stablyai/orca · error

[verify-skills-cli-runtime] ${outDir} is outside ${artifactR

Error message

[verify-skills-cli-runtime] ${outDir} is outside ${artifactRoot}

What it means

collectRuntimeClosure() realpaths both outDir and artifactRoot, then checks isOutsideRoot(artifactRoot, outDir). It throws when the build output directory itself is not contained within the artifact root — i.e. the verifier was pointed at an outDir that lives outside the package it's supposed to validate.

Source

Thrown at config/scripts/verify-skills-cli-runtime.cjs:111

    throw new Error(
      `[verify-skills-cli-runtime] missing runtime import "${specifier}" from ` +
        `${artifactPath(outDir, importer)}: ${detail}`
    )
  }
  if (isOutsideRoot(artifactRoot, resolved)) {
    throw new Error(
      `[verify-skills-cli-runtime] import "${specifier}" from ` +
        `${artifactPath(outDir, importer)} resolved outside ${artifactRoot}: ${resolved}`
    )
  }
  return resolved
}

function collectRuntimeClosure(outDir, artifactRoot = dirname(outDir)) {
  outDir = realpathSync(outDir)
  artifactRoot = realpathSync(artifactRoot)
  if (isOutsideRoot(artifactRoot, outDir)) {
    throw new Error(`[verify-skills-cli-runtime] ${outDir} is outside ${artifactRoot}`)
  }
  const entry = resolve(outDir, 'cli', 'index.js')
  if (!existsSync(entry)) {
    throw new Error(`[verify-skills-cli-runtime] missing entry ${entry}`)
  }
  const pending = [entry]
  const visited = new Set()

  while (pending.length > 0) {
    const file = pending.pop()
    if (!file || visited.has(file)) {
      continue
    }
    visited.add(file)
    const source = readFileSync(file, 'utf8')
    for (const specifier of runtimeImportSpecifiers(source, file)) {
      const resolved = resolveRuntimeImport(outDir, artifactRoot, file, specifier)
      if (resolved && !isOutsideRoot(artifactRoot, resolved) && /\.(?:c|m)?js$/.test(resolved)) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Confirm outDir is physically inside artifactRoot (print both realpaths).
  2. Pass an explicit artifactRoot that contains outDir instead of relying on the dirname default.
  3. Remove symlinks in the outDir path that escape the artifact root, or rebuild into a contained directory.
  4. Adjust the build config so dist emits inside the package boundary.
Defensive patterns

Strategy: validation

Validate before calling

// Pass an explicit artifactRoot and assert containment before calling collectRuntimeClosure:
const outDir = path.resolve(projectRoot, 'dist/skills')
const artifactRoot = path.resolve(projectRoot, 'dist')
if (!outDir.startsWith(artifactRoot + path.sep)) {
  throw new Error(`outDir ${outDir} must be inside artifactRoot ${artifactRoot}`)
}

Prevention

When it happens

Trigger: Calling collectRuntimeClosure with an outDir that is a sibling of or above artifactRoot; defaulting artifactRoot to dirname(outDir) when outDir is already at the root; realpath resolving a symlinked outDir to a location outside the artifact root.

Common situations: Misconfigured build output path; symlinked dist directory pointing outside the package; CI step that copies build output to an unexpected location before verification; caller passing absolute paths computed against the wrong base.

Related errors


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