From d341ccee3d486410663e85546b30c8c5ccc91cae Mon Sep 17 00:00:00 2001 From: Yogesh Kumar Date: Sat, 21 Mar 2026 23:01:19 +0530 Subject: [PATCH 1/2] Fix PVM compilation timeout and handle non-JSON error responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Increase PVM worker timeout from 30s to 90s (resolc is significantly slower than solc, especially with OpenZeppelin transitive deps) - Keep EVM worker timeout at 30s (solc is fast) - Increase Vercel maxDuration from 60s to 120s for headroom - Add safe JSON parsing in both compileSolidity and compileSoliditySources — catches HTML 502/504 gateway timeout responses and returns a user-friendly error instead of crashing Fixes #38 --- app/api/compile/route.ts | 12 +++++++----- lib/compile-client.ts | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/app/api/compile/route.ts b/app/api/compile/route.ts index 20936d5..9d84797 100644 --- a/app/api/compile/route.ts +++ b/app/api/compile/route.ts @@ -5,10 +5,11 @@ import { resolveAllImports, resolveAllImportsSources } from "@/lib/import-resolv import { checkRateLimit, getRateLimitReset } from "@/lib/rate-limiter"; export const runtime = "nodejs"; -export const maxDuration = 60; +export const maxDuration = 120; const MAX_BODY_SIZE = 512000; // 500KB -const WORKER_TIMEOUT_MS = 30_000; +const WORKER_TIMEOUT_EVM_MS = 30_000; +const WORKER_TIMEOUT_PVM_MS = 90_000; // resolc is significantly slower than solc interface CompileRequest { source?: string; @@ -28,8 +29,9 @@ interface CompileResponse { function compileInWorker( input: string, mode: string, - timeoutMs = WORKER_TIMEOUT_MS + timeoutMs?: number ): Promise { + const timeout = timeoutMs ?? (mode === "pvm" ? WORKER_TIMEOUT_PVM_MS : WORKER_TIMEOUT_EVM_MS); return new Promise((resolve, reject) => { const worker = new Worker(COMPILE_WORKER_CODE, { eval: true, @@ -37,8 +39,8 @@ function compileInWorker( }); const timer = setTimeout(() => { worker.terminate(); - reject(new Error("Compilation timed out after 30s")); - }, timeoutMs); + reject(new Error(`Compilation timed out after ${Math.round(timeout / 1000)}s`)); + }, timeout); worker.on("message", (msg) => { clearTimeout(timer); diff --git a/lib/compile-client.ts b/lib/compile-client.ts index 6510cb9..f1ad378 100644 --- a/lib/compile-client.ts +++ b/lib/compile-client.ts @@ -22,7 +22,24 @@ export async function compileSolidity( body: JSON.stringify({ source, mode }), }); - const data = await res.json(); + let data: any; + try { + data = await res.json(); + } catch { + // Server returned non-JSON (e.g., HTML 502/504 gateway timeout) + return { + success: false, + contracts: null, + contractNames: [], + errors: [ + { + message: `Server error (HTTP ${res.status}). PVM compilation may need more time — try again or use a simpler contract.`, + severity: "error", + }, + ], + warnings: [], + }; + } if (!res.ok) { return { @@ -91,7 +108,23 @@ export async function compileSoliditySources( body, }); - const data = await res.json(); + let data: any; + try { + data = await res.json(); + } catch { + return { + success: false, + contracts: null, + contractNames: [], + errors: [ + { + message: `Server error (HTTP ${res.status}). PVM compilation may need more time — try again or use a simpler contract.`, + severity: "error", + }, + ], + warnings: [], + }; + } if (!res.ok) { return { From cd5ec2b09696b90be2242611067636238dfe118c Mon Sep 17 00:00:00 2001 From: Yogesh Kumar Date: Sat, 21 Mar 2026 23:21:36 +0530 Subject: [PATCH 2/2] Tighten internal timeouts to leave headroom within maxDuration Reduce import resolution budget from 30s to 20s and PVM worker timeout from 90s to 80s. Worst case is now 20s + 80s = 100s, leaving 20s of headroom within the 120s maxDuration for cold start, request parsing, and response serialization. --- app/api/compile/route.ts | 2 +- lib/import-resolver.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/api/compile/route.ts b/app/api/compile/route.ts index 9d84797..1c5943a 100644 --- a/app/api/compile/route.ts +++ b/app/api/compile/route.ts @@ -9,7 +9,7 @@ export const maxDuration = 120; const MAX_BODY_SIZE = 512000; // 500KB const WORKER_TIMEOUT_EVM_MS = 30_000; -const WORKER_TIMEOUT_PVM_MS = 90_000; // resolc is significantly slower than solc +const WORKER_TIMEOUT_PVM_MS = 80_000; // resolc is slower; 20s resolver + 80s compile = 100s < 120s maxDuration interface CompileRequest { source?: string; diff --git a/lib/import-resolver.ts b/lib/import-resolver.ts index 27e41ac..ddb3cb2 100644 --- a/lib/import-resolver.ts +++ b/lib/import-resolver.ts @@ -15,7 +15,7 @@ const PER_FETCH_TIMEOUT_MS = 10_000; const MAX_FILE_SIZE = 500_000; // 500KB per file const MAX_FILES = 50; const MAX_ITERATIONS = 10; -const TOTAL_BUDGET_MS = 30_000; +const TOTAL_BUDGET_MS = 20_000; // 20s — leaves headroom within the 120s function limit interface ResolvedSources { sources: Record;