paperclipai/paperclip · error

PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive fini

Error message

PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive finite number

What it means

parseRunnerLiveCampaignCostLimit parses the PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD environment variable into the campaign's maximum spend in USD. When set, the value must parse via Number() as a finite number greater than 0; anything else (empty string, non-numeric text, 0, negative, Infinity) throws. Unset defaults to 12.

Source

Thrown at packages/paperclip-runner/src/eval/live-workflow-matrix.ts:20

import type {
  RunnerWorkflowEvalCase,
  RunnerWorkflowObservation,
  RunnerWorkflowProvider,
} from "./workflow-contracts.js";
import { RUNNER_WORKFLOW_CATALOG } from "./workflow-catalog.js";

export const RUNNER_LIVE_CANDIDATE_SCHEMA =
  "paperclip.runner.live-eval-candidate.v1" as const;
export const RUNNER_LIVE_SCHEDULE_SCHEMA =
  "paperclip.runner.live-eval-schedule.v1" as const;

export function parseRunnerLiveCampaignCostLimit(
  value: string | undefined,
): number {
  const parsed = Number(value ?? "12");
  if (!Number.isFinite(parsed) || parsed <= 0) {
    throw new Error(
      "PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive finite number",
    );
  }
  return parsed;
}

export function runnerLiveRotationWeek(generatedAt: string): number {
  const epochMs = Date.parse(generatedAt);
  if (!Number.isFinite(epochMs)) {
    throw new Error("Runner live rotation requires a valid generated-at time");
  }
  const epochWeek = Math.floor(epochMs / (7 * 86_400_000));
  return ((epochWeek % 7) + 7) % 7;
}

export type RunnerLiveAdapter =
  "codex_app_server" | "opencode_server" | "acpx_runtime";
export type RunnerLiveTier = "strong" | "inexpensive";

View on GitHub (pinned to 01ad858492)

Solutions

  1. Unset the variable entirely to use the built-in default of 12 USD.
  2. Set a plain positive finite decimal, e.g. PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD=25 (no currency symbols, commas, or units).
  3. Check for empty-string export in shell profiles/CI; an empty value becomes 0 and fails — use `unset PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD` instead.
  4. Verify in CI that the secret/variable interpolates to just the number without quotes or whitespace.

Example fix

// before
export PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD=""
// after
unset PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD  # or: export PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD=25
Defensive patterns

Strategy: validation

Validate before calling

export function isValidCostLimit(v: string | undefined): boolean {
  if (v === undefined) return true; // default 12 applies
  const n = Number(v);
  return Number.isFinite(n) && n > 0;
}
// usage: if (!isValidCostLimit(process.env.PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD)) throw ...

Try / catch

try {
  const limit = parseRunnerLiveCampaignCostLimit(process.env.PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD);
} catch {
  console.error("PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a plain positive finite number, e.g. 25; unset for default 12");
  process.exit(2);
}

Prevention

When it happens

Trigger: PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD is set to a non-numeric string ('twelve', '12 USD', ''), to 0, to a negative value, or to a value that Number() maps to NaN/Infinity ('1e400'). Note an empty string parses as 0, which fails the >0 check.

Common situations: Typo or stray characters in the env var in CI secrets; quoting issues leaving literal quotes in the value; setting it to '0' intending 'unlimited' (zero is rejected); locale-formatted numbers with commas ('1,50'); exporting it empty in a shell profile.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


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