{"record":{"id":"fac8d7c6e237eda1","repo":"Budibase/budibase","slug":"failed-to-verify-recaptcha-token-error-message","errorCode":null,"errorMessage":"Failed to verify recaptcha token - ${error.message}","messagePattern":"Failed to verify recaptcha token - (.+?)","errorType":"exception","errorClass":"UnexpectedError","httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/recaptcha.ts","lineNumber":61,"sourceCode":"\n    const { success } = await response.json()\n    const verified = success === true\n    if (verified) {\n      const sessionId = await setRecaptchaVerified()\n      const session: RecaptchaSessionCookie = {\n        sessionId,\n      }\n      utils.setCookie(ctx, session, Cookie.RecaptchaSession, {\n        sign: true,\n        sameSite: \"none\",\n      })\n    }\n\n    ctx.body = {\n      verified,\n    }\n  } catch (error: any) {\n    throw new UnexpectedError(\n      `Failed to verify recaptcha token - ${error.message}`\n    )\n  }\n}\n\nexport async function check(ctx: Ctx<void, CheckRecaptchaResponse>) {\n  const cookie = utils.getCookie<RecaptchaSessionCookie>(\n    ctx,\n    Cookie.RecaptchaSession\n  )\n  if (!cookie) {\n    ctx.body = { verified: false }\n    return\n  }\n  const verified = await isRecaptchaVerified(cookie.sessionId)\n  if (!verified) {\n    utils.clearCookie(ctx, Cookie.RecaptchaSession)\n    ctx.body = { verified: false }","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/recaptcha.ts#L43-L79","documentation":"If the server-side call to Google's `https://www.google.com/recaptcha/api/siteverify` throws (network failure, timeout, 5xx), `verify` wraps the underlying error in an `UnexpectedError` with this message, preserving the original message. It signals the verification attempt itself failed, not that the token was invalid — a `verified: false` response is returned when Google answers with success=false.","triggerScenarios":"Network egress to google.com blocked (firewall/proxy/air-gapped env), DNS failure, TLS issues, request timeout, or any exception thrown while contacting or parsing the Google siteverify response.","commonSituations":"Corporate firewalls blocking outbound HTTPS to google.com; running self-hosted Budibase in a container without internet; transient Google outages; proxy env vars not set for the Node process; IPv6/DNS misconfiguration.","solutions":["Ensure the server can reach https://www.google.com/recaptcha/api/siteverify (test with `curl -I` from the host/container)","Configure proxy support (HTTPS_PROXY env var or an HTTP agent) for the Node process","Retry the verification after transient network failures","Inspect the wrapped `error.message` for the root cause and fix accordingly","Consider mocking/short-circuiting reCAPTCHA verification in offline dev environments"],"exampleFix":"// before\n// container has no egress -> verify throws UnexpectedError\n// after: set proxy env for the server process\n// docker-compose.yml\n// environment:\n//   - HTTPS_PROXY=http://proxy.corp:8080\n//   - NO_PROXY=localhost,127.0.0.1","handlingStrategy":"try-catch","validationCode":"async function canReachGoogle() {\n  try { const r = await fetch(\"https://www.google.com/recaptcha/api/siteverify\", { method: \"HEAD\" }); return r.ok || r.status < 500 } catch { return false }\n}\n// gate verification on canReachGoogle()","typeGuard":null,"tryCatchPattern":"try {\n  const res = await verifyRecaptcha({ token })\n} catch (e) {\n  if (String(e.message).startsWith(\"Failed to verify recaptcha token\")) {\n    // network-level failure: retry with backoff or degrade gracefully\n  }\n}","preventionTips":["Whitelist google.com egress in firewalls/proxies for the server host","Set HTTPS_PROXY/HTTP_PROXY in containerized deployments","Add health checks for external dependencies before verification flows","Monitor the wrapped inner message to distinguish network vs config issues"],"tags":["network","recaptcha","external-api"],"backgroundTag":"upstream-request-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}