paperclipai/paperclip · error

runner_local_provider_artifact_missing

runner_local_provider_artifact_missing

Error message

runner_local_provider_artifact_missing: ${artifact} is absent; build @paperclipai/paperclip-runner TypeScript artifacts with build:typescript before starting a local JS-backed provider

What it means

resolveBuildOwnedCliArtifact resolves a build-owned CLI artifact by checking candidate filesystem paths and throws when none exist. The runner requires TypeScript-built artifacts of @paperclipai/paperclip-runner (dist output) before starting a local JS-backed provider. The throw guarantees the runner never boots a provider against missing/stale source-only state.

Source

Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:2706

type BuildOwnedCliArtifact =
  "acpx-runtime-sidecar.cjs" | "opencode-app-server-proxy.cjs";

function buildOwnedCliArtifactCandidates(
  artifact: BuildOwnedCliArtifact,
): readonly string[] {
  return [
    fileURLToPath(new URL(`../cli/${artifact}`, import.meta.url)),
    resolve(packageRoot, "dist", "cli", artifact),
  ];
}

function resolveBuildOwnedCliArtifact(
  artifact: BuildOwnedCliArtifact,
  candidates: readonly string[] = buildOwnedCliArtifactCandidates(artifact),
): string {
  const resolved = candidates.find((candidate) => existsSync(candidate));
  if (resolved) return resolved;
  throw new Error(
    `runner_local_provider_artifact_missing: ${artifact} is absent; build @paperclipai/paperclip-runner TypeScript artifacts with build:typescript before starting a local JS-backed provider`,
  );
}

function acpxProviderPackageAuthority(
  sidecarScript: string,
  ownerPackageRoot = packageRoot,
): {
  root: string;
  manifest: string;
} {
  const cliDirectory = dirname(sidecarScript);
  if (
    basename(sidecarScript) !== "acpx-runtime-sidecar.cjs" ||
    basename(cliDirectory) !== "cli" ||
    basename(dirname(cliDirectory)) !== "dist"
  ) {
    throw new Error(

View on GitHub (pinned to 01ad858492)

Solutions

  1. Run the TypeScript build for the runner package: pnpm --filter @paperclipai/paperclip-runner build:typescript (or repo-level equivalent).
  2. Verify the expected artifact (e.g. dist/cli/...) exists on disk before starting the provider.
  3. If building in CI, add the build:typescript step to the job before the provider start step.
  4. If the artifact should not be build-owned, point the provider at an installed/published package instead of the workspace source.

Example fix

// before
startLocalProvider(); // throws: artifact absent
// after
execSync('pnpm --filter @paperclipai/paperclip-runner build:typescript', { stdio: 'inherit' });
startLocalProvider();
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
if (!existsSync('node_modules/@paperclipai/paperclip-runner/dist/cli')) {
  throw new Error('runner TypeScript artifacts missing; run build:typescript first');
}

Type guard

const hasBuildArtifacts = (root: string): boolean => existsSync(join(root, 'dist'));

Try / catch

try {
  startLocalProvider();
} catch (err) {
  if ((err as Error).message.includes('runner_local_provider_artifact_missing')) {
    execSync('pnpm --filter @paperclipai/paperclip-runner build:typescript', { stdio: 'inherit' });
    startLocalProvider();
  } else throw err;
}

Prevention

When it happens

Trigger: Calling code that starts a local JS-backed provider (via resolveBuildOwnedCliArtifact) when the runner package's TypeScript build output has never been produced or was deleted, so no candidate path exists.

Common situations: Fresh clone without running build:typescript; a clean that removed dist/; CI checkout skipping the build step; starting runnerd directly with tsx/node without a prior build; pnpm install pruning generated artifacts.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/05f8aa6efc6fc2ad. Report an issue: GitHub.