paperclipai/paperclip · error

ACPX package ${packageName} has invalid package metadata

Error message

ACPX package ${packageName} has invalid package metadata

What it means

readPackageJson parses a package.json for an ACPX package and requires the result to be a plain object. The JSON parsed successfully but is not of the expected shape — an array, string, number, or null — so the metadata cannot be used as AcpxPackageMetadata. This guards the downstream version/dependency checks against malformed metadata.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts:825

}

async function readPackageJson(
  packageJsonPath: string,
  packageName: string,
): Promise<AcpxPackageMetadata> {
  const bytes = await readBoundedRegularFile(
    packageJsonPath,
    MAX_PACKAGE_JSON_BYTES,
    `${packageName} package.json`,
  );
  let value: unknown;
  try {
    value = JSON.parse(bytes.toString("utf8"));
  } catch {
    throw new Error(`ACPX package ${packageName} has malformed package.json`);
  }
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
    throw new Error(`ACPX package ${packageName} has invalid package metadata`);
  }
  return value as AcpxPackageMetadata;
}

async function verifyQualifiedRuntimeExecutable(input: {
  profile: QualifiedAcpxProfile;
  runtimePackage: AcpxPackageMetadata;
  runtimePackageJsonPath: string;
  resolvePackageJson: AcpxPackageJsonResolver;
}): Promise<VerifiedAcpxRuntimeExecutable | null> {
  const qualification =
    input.profile.agent === "claude"
      ? process.platform === "darwin" && (process.arch === "arm64" || process.arch === "x64")
        ? QUALIFIED_CLAUDE_DARWIN_RUNTIMES[process.arch]
        : QUALIFIED_CLAUDE_LINUX_X64_RUNTIME
      : input.profile.agent === "codex"
        ? QUALIFIED_CODEX_LINUX_X64_RUNTIME
        : null;

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect the package.json at the resolved path and restore a valid top-level JSON object with name/version fields.
  2. Reinstall the affected package so a correct package.json is written by the package manager.
  3. Verify resolvePackageJson/realpath pointed at the intended package's package.json, not an unrelated JSON file.
  4. If the file is generated, fix the generator so it always emits a single JSON object at top level.

Example fix

// before (package.json)
[]
// after
{ "name": "@anthropic-ai/claude-code", "version": "2.0.14" }
Defensive patterns

Strategy: type-guard

Validate before calling

const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
if (typeof pkg !== "object" || pkg === null || Array.isArray(pkg)) {
  throw new Error(`${pkgJsonPath} is not a package.json object; reinstall the package`);
}

Type guard

function isPackageMetadata(v) {
  return typeof v === "object" && v !== null && !Array.isArray(v) && typeof v.name === "string";
}

Try / catch

try {
  await verifyQualifiedAcpxInstallation(input);
} catch (e) {
  if (e.message.includes("has invalid package metadata")) {
    await reinstallAffectedPackage();
    await verifyQualifiedAcpxInstallation(input);
  } else throw e;
}

Prevention

When it happens

Trigger: readPackageJson (called via serverPackage, dependencyPackage, executablePackage, or verifyQualifiedAcpxInstallation) reads a package.json whose top-level JSON value is valid JSON but not a non-null, non-array object.

Common situations: A package.json replaced by a lockfile-style array, an error page, or a build artifact; hand-edited file wrapping the object in an array; a placeholder file (e.g. `[]` or `""`) left by a failed install; resolving the wrong file path that happens to contain valid non-object JSON.

Related errors


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