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

  1. Confirm a push run exists for the sha on master: https://github.com/paperclipai/paperclip/actions/workflows/cloud-readiness.yml, filtered by the commit.
  2. Rerun Cloud readiness (workflow_dispatch or re-run) and then retry the release poll for a fresh 45-minute window.
  3. Check whether the run is stuck on an environment/branch-protection approval and approve it.
  4. If runs legitimately take longer than 45 minutes, raise timeoutMs passed to waitForSourceVerification.
  5. 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

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.

Related errors


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)