paperclipai/paperclip · error · Error
Cloud source verification timed out for
Error message
Cloud source verification timed out for ${sha}. Rerun Cloud readiness before retrying the release. What it means
waitForSourceVerification polls readSourceVerification every 30s for up to 45 minutes (default timeoutMs). If the Cloud source verified v1 job has not completed successfully for the sha by the deadline — without ever observing a completed non-success verdict — it throws this timeout. Callers are told to rerun Cloud readiness before retrying the release.
Solutions
- Confirm a push run exists for the sha on master: https://github.com/paperclipai/paperclip/actions/workflows/cloud-readiness.yml, filtered by the commit.
- Rerun Cloud readiness (workflow_dispatch or re-run) and then retry the release poll for a fresh 45-minute window.
- Check whether the run is stuck on an environment/branch-protection approval and approve it.
- If runs legitimately take longer than 45 minutes, raise timeoutMs passed to waitForSourceVerification.
- Verify the sha passed as argv[2] is the full 40-char lowercase commit sha.
Example fix
// before: default 45-minute wait
const proof = await waitForSourceVerification(sha, { api, timeoutMs });
// after: allow slow CI
const proof = await waitForSourceVerification(sha, { api, timeoutMs: 90 * 60_000 }); Defensive patterns
Strategy: try-catch
Validate before calling
// before polling: confirm a run even exists for the sha
const wf = await api('/repos/paperclipai/paperclip/actions/workflows/cloud-readiness.yml');
const runs = await api(`/repos/paperclipai/paperclip/actions/workflows/${wf.id}/runs?head_sha=${sha}&event=push&branch=master&per_page=1`);
if (runs.total_count === 0) throw new Error('No Cloud readiness push run for this sha yet — push or trigger one first'); Try / catch
try {
const proof = await waitForSourceVerification(sha, { api, timeoutMs });
} catch (e) {
if (e.message.startsWith('Cloud source verification timed out')) {
console.error('Not verified within the window — rerun Cloud readiness, then retry the release.');
}
} Prevention
- Trigger Cloud readiness immediately after pushing the sha so the 45-minute window is not wasted waiting in queue.
- Approve environment/branch-protection gates promptly; approvals pause the clock invisibly to the poller.
- Pass the full 40-char lowercase sha — partial or uppercase shas never match head_sha.
- Raise timeoutMs for releases during known GitHub congestion.
When it happens
Trigger: The push-triggered Cloud readiness run for the sha is queued/running longer than 45 minutes; no matching run exists at all for the sha (returns undefined every poll); a rerun keeps the attempt in progress past the deadline; workflow waits on required approvals/environments.
Common situations: GitHub Actions congestion delaying job start; the workflow run stuck on a pending environment approval; sha pushed but workflow disabled (cloud-readiness.yml on a branch where Actions is off) so no run ever starts; typo'd/not-full sha so the head_sha filter never matches.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Cloud artifacts timed out for
- Cloud source verification did not pass for
- Preview workflow definitions must run from master.
- --agent-name cannot be empty.
- --api-key and --api-key-env are mutually exclusive.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/6896739d15d829d6.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/cloud-source-verification.mjs:151
await pause(response);
}
};
}
export async function waitForSourceVerification(sha, {
api, now = Date.now, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
timeoutMs = 45 * 60_000, intervalMs = 30_000, log = console.log,
} = {}) {
assertSha(sha);
const deadline = now() + timeoutMs;
log(`Waiting for ${sourceVerificationJob} for ${sha}.`);
while (now() < deadline) {
const result = await readSourceVerification(sha, api);
if (result) return result;
const remaining = deadline - now();
if (remaining > 0) await sleep(Math.min(intervalMs, remaining));
}
throw new Error(`Cloud source verification timed out for ${sha}. Rerun Cloud readiness before retrying the release.`);
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
try {
if (!process.env.GITHUB_TOKEN) throw new Error("GITHUB_TOKEN with Actions read access is required.");
// One deadline for both layers: the reader stops retrying when the poll it
// serves is out of time, instead of extending the wait past its timeout.
const timeoutMs = 45 * 60_000;
const deadline = Date.now() + timeoutMs;
const api = createActionsReader({ token: process.env.GITHUB_TOKEN, deadlineAt: () => deadline });
const proof = await waitForSourceVerification(process.argv[2], { api, timeoutMs });
const message = `Source verification passed for ${proof.sha}: https://github.com/${repository}/actions/runs/${proof.runId}/attempts/${proof.attempt} (job ${proof.jobId}).`;
console.log(message);
if (process.env.GITHUB_STEP_SUMMARY) await appendFile(process.env.GITHUB_STEP_SUMMARY, `${message}\n`);
} catch (error) {
console.error(error.message);
process.exitCode = 1;
}View on GitHub (pinned to 3f1d897a7c)