paperclipai/paperclip · error · Error

an immutable README asset ref is required

Error message

an immutable README asset ref is required

What it means

prepareNpmReadme() rewrites doc asset links in the README to point at an immutable git ref (commit SHA or tag) on raw.githubusercontent.com, so the npm-published README never references moving resources like 'main'. It refuses to run without an explicit assetRef because publishing relative/mutable links would break asset rendering on npm.

Solutions

  1. Pass an immutable ref (commit SHA or release tag) as the third CLI argument or second function argument, e.g. node scripts/prepare-npm-readme.mjs README.md dist/README.md abc1234.
  2. In the release script, resolve the ref with git rev-parse HEAD (or the tag) and fail early if empty before invoking prepareNpmReadme.
  3. If running programmatically, guard the call: if (!assetRef) throw before calling, to get a clearer stack at the call site.

Example fix

// before
prepareNpmReadme(readme, process.env.GIT_REF ?? "")
// after
const ref = execSync("git rev-parse HEAD").toString().trim();
if (!ref) throw new Error("cannot resolve immutable asset ref");
prepareNpmReadme(readme, ref)
Defensive patterns

Strategy: try-catch

Validate before calling

const ref = process.argv[2];
if (!ref || ref.trim() === '') throw new Error('prepareNpmReadme: pass an immutable commit SHA or tag as assetRef');

Type guard

const isImmutableRef = (r) => typeof r === 'string' && /^[0-9a-f]{40}$|^(v?\d+\.\d+\.\d+)$/.test(r.trim());

Try / catch

try { const out = prepareNpmReadme(readme, ref); } catch (e) { if (e.message.includes('immutable README asset ref')) { console.error('Resolve the release SHA/tag first: git rev-parse HEAD'); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: Calling prepareNpmReadme(readme, assetRef) with assetRef === "" / undefined / null — e.g. the CLI wrapper invoked with only two arguments, or a release script computing the ref from an empty git describe output.

Common situations: A release pipeline step that forgets to pass the commit SHA/tag; a git command that resolves to an empty string (detached HEAD quirks, shallow clone without tags) feeding an empty ref into the script; manually running the module from another script without the third argument.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/b51612fc96ece811. Report an issue: GitHub.

Appendix: source

Thrown at scripts/prepare-npm-readme.mjs:7

import { readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

export function prepareNpmReadme(readme, assetRef) {
  if (!assetRef) {
    throw new Error("an immutable README asset ref is required");
  }

  const assetBaseUrl =
    `https://raw.githubusercontent.com/paperclipai/paperclip/${assetRef}/doc/assets/`;

  return readme.replace(
    /((?:src|srcset)=["'])([^"']*)(["'])/g,
    (_match, prefix, value, suffix) =>
      `${prefix}${value.replace(
        /(^|,\s*)doc\/assets\//g,
        `$1${assetBaseUrl}`,
      )}${suffix}`,
  );
}

const isDirectRun =
  process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);

View on GitHub (pinned to 3f1d897a7c)