paperclipai/paperclip · error · Error

${label} smoke artifacts are older than their source. Rebuil

Error message

${label} smoke artifacts are older than their source. Rebuild the targeted artifacts before running the smoke.

What it means

assertArtifactsFresh compares the newest mtime of source files against the oldest mtime of the built artifacts used by the smoke. If any source is newer than any artifact, the stale-artifact guard throws so the smoke does not test outdated binaries. It is a freshness invariant, not a build error.

Source

Thrown at packages/paperclip-runner/scripts/run-local-provider-smoke.mjs:122

      if (!skipDirectory(path)) {
        files.push(...(await filesUnder(path, include, skipDirectory)));
      }
    } else if (entry.isFile() && include(path)) {
      files.push(path);
    }
  }
  return files;
}

async function assertArtifactsFresh(label, sources, artifacts) {
  const sourceTimes = await Promise.all(
    sources.map(async (source) => (await stat(source)).mtimeMs),
  );
  const artifactTimes = await Promise.all(
    artifacts.map(async (artifact) => (await stat(artifact)).mtimeMs),
  );
  if (Math.max(...sourceTimes) > Math.min(...artifactTimes)) {
    throw new Error(
      `${label} smoke artifacts are older than their source. Rebuild the targeted artifacts before running the smoke.`,
    );
  }
}

const profiles = parseProfiles(process.argv.slice(2));
const packageRoot = resolve(import.meta.dirname, "..");
const runnerd = resolve(
  packageRoot,
  "runner",
  "target",
  "debug",
  process.platform === "win32" ? "paperclip-runnerd.exe" : "paperclip-runnerd",
);
const requiredArtifacts = [
  runnerd,
  resolve(packageRoot, "dist", "eval", "index.js"),
  ...(profiles.some((profile) => profile.startsWith("runner-acpx-"))

View on GitHub (pinned to 01ad858492)

Solutions

  1. Rebuild the targeted artifacts: run `pnpm build:typescript` and `pnpm build:runner-binaries`, then rerun the smoke.
  2. If only one artifact set is stale, rebuild just that set so its mtime is newer than all sources.
  3. Avoid touching sources between build and smoke; if a git operation refreshed mtimes unnecessarily, rebuild.

Example fix

// before
pnpm smoke:local-provider -- --profile all
// after
pnpm build:typescript && pnpm build:runner-binaries && pnpm smoke:local-provider -- --profile all
Defensive patterns

Strategy: validation

Validate before calling

const { statSync } = require('fs');
const newestSource = Math.max(...srcs.map(s => statSync(s).mtimeMs));
const oldestArtifact = Math.min(...arts.map(a => statSync(a).mtimeMs));
if (newestSource > oldestArtifact) console.log('rebuild before smoke');

Prevention

When it happens

Trigger: Editing TypeScript or Rust sources (or any file in the sources list) after the last build, then running `pnpm smoke:local-provider` without rebuilding. Also triggered by filesystem operations that touch source mtimes (git checkout, rebase, stash pop) after a build.

Common situations: Pulling new commits that touch sources while keeping dist/ artifacts, switching branches, or building once and iterating on code before rerunning the smoke.

Related errors


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