decolua/9router · error

Deployment timed out

Error message

Deployment timed out

What it means

pollDeployment gives up after maxMs (default 120000 ms) if the deployment never reaches READY, ERROR, or CANCELED, throwing `Deployment timed out`. This is a client-side deadline, not a Vercel-reported failure — the deployment may still be building. The polling loop sleeps 3s between GET /v13/deployments/<id> calls and stops when the clock runs out.

Source

Thrown at src/app/api/proxy-pools/vercel-deploy/route.js:55

    headers: response.headers,
  });
}
`;

async function pollDeployment(deploymentId, token, maxMs = 120000) {
  const start = Date.now();
  while (Date.now() - start < maxMs) {
    const res = await fetch(`${VERCEL_API}/v13/deployments/${deploymentId}`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    const data = await res.json();
    if (data.readyState === "READY") return data;
    if (data.readyState === "ERROR" || data.readyState === "CANCELED") {
      throw new Error(`Deployment failed: ${data.readyState}`);
    }
    await new Promise((r) => setTimeout(r, 3000));
  }
  throw new Error("Deployment timed out");
}

// POST /api/proxy-pools/vercel-deploy
export async function POST(request) {
  try {
    const body = await request.json();
    const vercelToken = body.vercelToken;
    const projectName = body.projectName?.trim() || `relay-${Date.now().toString(36)}`;

    if (!vercelToken) {
      return NextResponse.json({ error: "Vercel API token is required" }, { status: 400 });
    }

    // Deploy relay function to Vercel
    const deployRes = await fetch(`${VERCEL_API}/v13/deployments`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${vercelToken}`,

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Increase the maxMs deadline when calling pollDeployment (e.g. pollDeployment(deploymentId, vercelToken, 300000) for 5 minutes).
  2. Check the deployment status manually in the Vercel dashboard or via GET /v13/deployments/<id> — if it eventually becomes READY, the relay URL (https://<url>) is usable even though this call threw.
  3. Retry the POST; a fresh deployment often builds faster once the queue clears.
  4. Reduce build time: the relay project is minimal, so long builds usually indicate Vercel-side queueing — retry at a different time or upgrade the plan for priority builds.

Example fix

// before
const ready = await pollDeployment(deploymentId, vercelToken);
// after
const ready = await pollDeployment(deploymentId, vercelToken, 300000); // 5 min
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call validation possible; choose a deadline proportional to plan/queue
const maxMs = process.env.VERCEL_DEPLOY_TIMEOUT_MS ? Number(process.env.VERCEL_DEPLOY_TIMEOUT_MS) : 300000;

Try / catch

try {
  const ready = await pollDeployment(id, token, 300000);
} catch (err) {
  if (err.message === "Deployment timed out") {
    // Check status out-of-band; the deployment may still complete
    const final = await fetch(`${VERCEL_API}/v13/deployments/${id}`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json());
    if (final.readyState === "READY") return final; // recover late build
  }
  throw err;
}

Prevention

When it happens

Trigger: A deployment takes longer than 2 minutes to reach READY (slow build, build queue congestion on free plans, large project, or Vercel platform delays), so the while (Date.now() - start < maxMs) loop exits before readyState changes.

Common situations: Free/Hobby plan build queues during peak times, deployments stuck in QUEUED/INITIALIZING state, slow cold builds, or network slowness making each poll take longer so fewer polls fit in the window.

Understand the failure class

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/5367d9477a732e93. Report an issue: GitHub.