paperclipai/paperclip · error · Error
Migrator producer lookup failed: HTTP
Error message
Migrator producer lookup failed: HTTP ${response.status} What it means
migratorPublished() polls the GitHub Actions API for cloud-migrator-artifacts workflow runs on the given commit. When any page request returns a non-OK HTTP status it throws this error with the status code embedded. It is a fail-closed API transport check.
Solutions
- Check GH_TOKEN validity and Actions read scope, then rerun; note the script retries at the waitForCloudArtifacts poll level, so transient statuses may self-heal on the next 20s poll.
- If HTTP 403 with x-ratelimit-remaining: 0, wait for the rate-limit window to reset or use an authenticated token.
- Verify api.github.com is reachable and the paperclipai/paperclip repository still exists at that name.
Example fix
// before
const token = process.env.GH_TOKEN; // undefined or expired
// after
if (!process.env.GH_TOKEN) throw new Error("Set GH_TOKEN with Actions read scope before polling.");
const token = process.env.GH_TOKEN; Defensive patterns
Strategy: retry
Validate before calling
// preflight
const probe = await fetch("https://api.github.com/rate_limit", { headers: token ? { Authorization: `Bearer ${token}` } : {} });
if (!probe.ok) throw new Error(`GitHub API unreachable/unauthorized: HTTP ${probe.status}`); Try / catch
try {
await waitForCloudArtifacts(sha);
} catch (error) {
if (/Migrator producer lookup failed/.test(error.message)) {
console.error("GitHub API error — check GH_TOKEN scope and rate limits:", error.message);
process.exitCode = 1;
} else throw error;
} Prevention
- Always set GH_TOKEN with Actions read scope before running
- Monitor rate limit via /rate_limit in long polls
- Wrap the readiness check in the release script's own retry with backoff
When it happens
Trigger: The fetch to api.github.com/repos/paperclipai/paperclip/actions/workflows/cloud-migrator-artifacts.yml/runs returns 401/403/404/422/5xx — e.g. expired GH_TOKEN, rate-limited 403, renamed repository, or a GitHub outage.
Common situations: Expired or missing GitHub token in GH_TOKEN; hitting the unauthenticated 60 req/hr rate limit; GHE/proxy interference; GitHub API incident; transient network failure within the 30s AbortSignal timeout.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- GitHub Actions read failed
- github_webhook_recovery_transport
- railway_workspace_discovery_failed
- Anthropic Managed Agents request failed with HTTP
- Artifact download failed: HTTP
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/81e81b68c05fe077.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/cloud-readiness.mjs:21
import { execFileSync } from "node:child_process";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { imageExists, versionFor } from "./preview-artifacts.mjs";
import { verifyPublished } from "./cloud-migrator-artifacts.mjs";
const repository = "paperclipai/paperclip";
const workflow = ".github/workflows/cloud-migrator-artifacts.yml";
export async function migratorPublished(sha, fetchImpl, token) {
let pending = false;
const failures = [];
for (let page = 1; page <= 10; page++) {
const response = await fetchImpl(`https://api.github.com/repos/${repository}/actions/workflows/cloud-migrator-artifacts.yml/runs?branch=master&head_sha=${sha}&per_page=100&page=${page}`, {
headers: { Accept: "application/vnd.github+json", ...(token ? { Authorization: `Bearer ${token}` } : {}) },
redirect: "error", signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(`Migrator producer lookup failed: HTTP ${response.status}`);
const body = await response.json();
if (!Array.isArray(body.workflow_runs) || !Number.isSafeInteger(body.total_count) || body.total_count < 0 ||
(page === 1 && (body.total_count === 0) !== (body.workflow_runs.length === 0))) throw new Error("Invalid migrator producer response.");
if (body.total_count === 0) return false;
for (const run of body.workflow_runs) {
if (run.head_sha !== sha || run.head_branch !== "master" || run.path !== workflow ||
run.head_repository?.id !== 1170821064 || run.head_repository.full_name !== repository ||
!["push", "workflow_dispatch"].includes(run.event)) throw new Error("Migrator producer identity mismatch.");
// Publication is immutable. A later failed manual run must not hide a
// successful exact-source publisher; the signed bundle is checked next.
if (run.status === "completed" && run.conclusion === "success") return true;
if (run.status !== "completed") pending = true;
else failures.push(`${run.id}: ${run.conclusion}`);
}
if (page * 100 >= body.total_count) {
if (pending) return false;
throw new Error(`Migrator producers failed: ${failures.join(", ")}.`);
}View on GitHub (pinned to 3f1d897a7c)