paperclipai/paperclip · error · Error
Migrator producers failed
Error message
Migrator producers failed: ${failures.join(", ")}. What it means
When all pages of migrator runs have been examined, none are pending, and none succeeded, the script throws listing the failed run ids and conclusions. Publication is fail-closed: a failed publisher run blocks rather than silently waiting.
Solutions
- Read the failure list (runId: conclusion) and open the corresponding GitHub Actions run to find the failing step.
- Fix the underlying build/publish failure (npm pack output, AWS credentials on the publish job, bundle validation) and re-run the workflow on the same SHA.
- Note: if an earlier run for the same SHA succeeded, that success is honored and this error will not throw — only SHA-level total failure reaches this path.
Example fix
// before // no run for sha, or all failed // after gh workflow run cloud-migrator-artifacts.yml --ref master -f sha=<sha> # then let readiness poll again
Defensive patterns
Strategy: try-catch
Try / catch
try {
await waitForCloudArtifacts(sha);
} catch (error) {
const m = error.message.match(/^Migrator producers failed: (.*)\.$/);
if (m) {
for (const entry of m[1].split(", ")) {
const [runId, conclusion] = entry.split(": ");
console.error(`See https://github.com/paperclipai/paperclip/actions/runs/${runId} (${conclusion})`);
}
process.exitCode = 1;
} else throw error;
} Prevention
- Watch the migrator workflow after each master push
- Give the publish job valid AWS credentials so uploads do not fail
- Fail the PR pipeline early if the publish job fails instead of retrying blindly
When it happens
Trigger: Every completed cloud-migrator-artifacts run for the SHA on master ended with a failure/cancelled conclusion (e.g. build or publish job failed) and no run is still in progress.
Common situations: The publish job failed on S3 upload (missing AWS credentials), the bundle validation failed on a bad package tarball, or someone cancelled the run; a manual workflow_dispatch rerun failed after an earlier failure.
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
- Cloud source verification did not pass for
- Cloud artifacts timed out for
- Cloud readiness job listing is incomplete.
- Cloud readiness job listing is malformed.
- Cloud readiness run listing is incomplete.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/e0626b7e5597a2ac.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/cloud-readiness.mjs:38
});
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(", ")}.`);
}
}
throw new Error("Too many migrator producer runs to establish publication.");
}
export function verifyManifestProvenance(bytes, sha, { exec = execFileSync } = {}) {
versionFor(sha);
const scratch = mkdtempSync(path.join(os.tmpdir(), "cloud-readiness-attestation-"));
try {
const file = path.join(scratch, "manifest.json");
writeFileSync(file, bytes);
exec("gh", ["attestation", "verify", file, "--repo", repository,
"--source-digest", sha, "--source-ref", "refs/heads/master",
"--cert-identity", `https://github.com/${repository}/${workflow}@refs/heads/master`,
"--deny-self-hosted-runners"], { stdio: "inherit", timeout: 60_000 });
} finally { rmSync(scratch, { recursive: true, force: true }); }
}
View on GitHub (pinned to 3f1d897a7c)