stablyai/orca · error

[verify-packaged-plugin-resources] missing launch directory

Error message

[verify-packaged-plugin-resources] missing launch directory at ${launchRoot}

What it means

Thrown by the packaged plugin resource verifier when statSync on the plugins/launch directory inside the Resources dir either fails (ENOENT — statSync throws, but the check is on .isDirectory() so a throw propagates) or the path exists but is not a directory. The launch directory is the root where all bundled plugins and their index files live; its absence means the plugin packaging step produced no output.

Source

Thrown at config/scripts/verify-packaged-plugin-resources.cjs:73

    hash.update(readFileSync(file.path))
  }
  return hash.digest('hex')
}

function readJsonFile(path, label) {
  try {
    return JSON.parse(readFileSync(path, 'utf8'))
  } catch (error) {
    throw new Error(
      `[verify-packaged-plugin-resources] invalid ${label} at ${path}: ${error instanceof Error ? error.message : String(error)}`
    )
  }
}

function verifyPackagedPluginResources(resourcesDir) {
  const launchRoot = join(resourcesDir, 'plugins', 'launch')
  if (!statSync(launchRoot).isDirectory()) {
    throw new Error(`[verify-packaged-plugin-resources] missing launch directory at ${launchRoot}`)
  }
  const index = readJsonFile(join(launchRoot, 'bundled-plugins.json'), 'bundled plugin index')
  readJsonFile(join(launchRoot, 'orca-marketplace.json'), 'marketplace index')
  if (index?.version !== 1 || !Array.isArray(index.plugins) || index.plugins.length === 0) {
    throw new Error('[verify-packaged-plugin-resources] bundled plugin index is empty or invalid')
  }
  const resolvedRoot = resolve(launchRoot)
  for (const entry of index.plugins) {
    if (
      typeof entry?.pluginKey !== 'string' ||
      typeof entry.path !== 'string' ||
      !/^[0-9a-f]{64}$/.test(entry.contentHash)
    ) {
      throw new Error('[verify-packaged-plugin-resources] bundled plugin entry is invalid')
    }
    const pluginRoot = resolve(launchRoot, entry.path)
    const fromRoot = relative(resolvedRoot, pluginRoot)
    if (!fromRoot || fromRoot === '..' || fromRoot.startsWith(`..${sep}`) || isAbsolute(fromRoot)) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Check if the directory exists in the packaged output: ls <resourcesDir>/plugins/launch/.
  2. Verify the electron-builder extraResources or files configuration includes the plugins/launch directory.
  3. Ensure the plugin build/bundling step runs before electron-builder packaging and outputs to the expected location.
  4. Check the build logs for errors in the plugin packaging pipeline.
Defensive patterns

Strategy: validation

Validate before calling

// Before running verification, check the launch directory exists.
const { statSync } = require('node:fs')
const { join } = require('node:path')

function preCheckLaunchDir(resourcesDir) {
  const launchRoot = join(resourcesDir, 'plugins', 'launch')
  try {
    if (!statSync(launchRoot).isDirectory()) {
      return { ok: false, message: `${launchRoot} exists but is not a directory` }
    }
    return { ok: true }
  } catch {
    return { ok: false, message: `${launchRoot} does not exist — plugin packaging step may have been skipped` }
  }
}

Prevention

When it happens

Trigger: verifyPackagedPluginResources(resourcesDir) is called on a packaged app where <resourcesDir>/plugins/launch does not exist. This means the electron-builder extraResources or files configuration that copies plugins into the package was not applied, or the source plugin directory was empty during packaging.

Common situations: The plugin build step was skipped or failed before packaging; electron-builder's extraResources config for plugins was removed or misconfigured; the plugins were written to a different directory than plugins/launch; the packaging ran from a clean checkout where plugins hadn't been built yet.

Related errors


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