paperclipai/paperclip · error
Runner live rotation requires a valid generated-at time
Error message
Runner live rotation requires a valid generated-at time
What it means
runnerLiveRotationWeek converts a generated-at timestamp into a stable rotation index (0-6) used to pick which live adapter candidates run this week. It requires Date.parse to yield a finite epoch value; an unparseable or missing timestamp string throws this error, since rotation cannot be computed deterministically without a valid instant.
Source
Thrown at packages/paperclip-runner/src/eval/live-workflow-matrix.ts:30
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";
export interface RunnerLiveEvalCandidate {
schema: typeof RUNNER_LIVE_CANDIDATE_SCHEMA;
id: string;
slotId: string;
adapter: RunnerLiveAdapter;
provider: RunnerWorkflowProvider;
model: string;
tier: RunnerLiveTier;
reasoningEffort?: string;View on GitHub (pinned to 01ad858492)
Solutions
- Use a valid ISO 8601 UTC timestamp for generatedAt, e.g. new Date().toISOString() produces '2026-09-02T12:00:00.000Z'.
- Regenerate the schedule manifest with the tooling that produces it instead of hand-editing the timestamp field.
- Check for unsubstituted template placeholders or empty strings in the manifest's generatedAt field.
- If parsing external input, validate with Number.isFinite(Date.parse(v)) before calling and surface the raw value in the failure.
Example fix
// before
runnerLiveRotationWeek("09/02/2026 12:00 PM")
// after
runnerLiveRotationWeek(new Date().toISOString()) // "2026-09-02T12:00:00.000Z" Defensive patterns
Strategy: validation
Validate before calling
function isValidGeneratedAt(v: string): boolean {
return typeof v === "string" && v.length > 0 && Number.isFinite(Date.parse(v));
}
// usage: if (!isValidGeneratedAt(schedule.generatedAt)) throw new Error(`bad generatedAt: ${JSON.stringify(schedule.generatedAt)}`); Type guard
function isParsableDate(v: unknown): v is string {
return typeof v === "string" && v.trim() !== "" && Number.isFinite(Date.parse(v));
} Try / catch
try {
const week = runnerLiveRotationWeek(schedule.generatedAt);
} catch (error) {
if (String(error).includes("valid generated-at")) {
console.error(`schedule.generatedAt is not a parseable date: ${JSON.stringify(schedule.generatedAt)}; regenerate the manifest`);
}
throw error;
} Prevention
- Always write generatedAt with new Date().toISOString() (ISO 8601 UTC), never locale-formatted strings.
- Regenerate schedule manifests with the producing tooling rather than hand-editing timestamps.
- Search manifests for unsubstituted placeholders ('${generatedAt}') or empty strings before running rotation.
- Validate schedule JSON against RUNNER_LIVE_SCHEDULE_SCHEMA before passing fields to rotation helpers.
When it happens
Trigger: Calling runnerLiveRotationWeek with a string Date.parse cannot parse: an empty string, a non-ISO formatted date, a localized date, 'undefined'/'null' as literal strings, or a truncated timestamp from a hand-edited schedule manifest (RUNNER_LIVE_SCHEDULE_SCHEMA) — called from first/second rotation selection paths.
Common situations: Hand-editing a live-eval schedule JSON and mistyping generatedAt; generating the manifest with a non-ISO8601 date format; a template leaving ${generatedAt} unsubstituted; timezone-localized strings that V8's Date.parse rejects in some runtimes.
Related errors
- PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive fini
- unknown Runner live eval candidate: ${id}
- unknown Runner live eval case: ${id}
- Runner live eval selection limit must be a positive integer
- ${label} must be an integer between 1 and ${maximum}.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-02).
Data as JSON: /api/errors/c7d43e15c014e000.
Report an issue: GitHub.