Error: "RIBAUNT_SECRET environment variable is not set!"
Error: "RIBAUNT_SECRET environment variable is not set!"
Cause: For hosted runtimes (Vercel, Railway, Fly.io, etc.), set
RIBAUNT_SECRET is missing from your environment, or it is not loaded into the process before the first call to createChallenge or verifySolution.Fix: Ensure the variable is defined before your server handles its first request. If you use a .env file, load it at the top of your entry point with a tool like dotenv:RIBAUNT_SECRET through your platform’s environment variable dashboard rather than committing it to source control. Rotate the secret immediately if it is ever accidentally exposed.Widget error: "Web Crypto API is unavailable. Use HTTPS or localhost."
Widget error: "Web Crypto API is unavailable. Use HTTPS or localhost."
verifySolution returns false — reason: "expired-token"
verifySolution returns false — reason: "expired-token"
Cause: The challenge token’s TTL elapsed before the browser submitted its solution. This can happen on pages that take a long time to load, forms where users spend several minutes before submitting, or if the server and client clocks are significantly skewed.Fix: Increase
ttlSeconds in your createChallenge call to give users more time. The default is 30 seconds; consider 120–300 for complex pages or forms:verifySolution returns false — reason: "replay-detected"
verifySolution returns false — reason: "replay-detected"
Cause: The same challenge tokens were submitted more than once. This is intentional — Ribaunt’s default
local replay store marks tokens as consumed on first use and rejects any subsequent submission.Fix: If this is happening in normal user flows, it most likely means your frontend is re-submitting the same tokens (e.g. on form retry). Issue fresh tokens for each attempt by calling your challenge endpoint again before re-submitting.If you are seeing this in serverless or multi-instance deployments, the issue is that each function invocation has its own in-memory store. Tokens consumed in one instance are invisible to others. Switch to replayPrevention: 'remote' with a distributed store:Widget does not start verifying automatically
Widget does not start verifying automatically
Cause: The Also check that
auto-verify attribute is absent or the widget is in a disabled state, which prevents auto-verify from firing even when set.Fix: Add auto-verify="true" to the HTML element, or autoVerify={true} in the React wrapper:disabled is either absent or explicitly set to "false". While the widget is disabled, auto-verify will not trigger.Widget not appearing or JS error on load
Widget not appearing or JS error on load
Cause: The widget script is not loading correctly. Common causes include an incorrect path to the built file, loading the script without If you are bundling the widget yourself, make sure your bundler resolves the
type="module", or a bundler that is not resolving the package’s browser export correctly.Fix: Load the widget script as a module and verify the path points to dist/widget-browser.js:browser export condition from the Ribaunt package. Check your framework’s documentation for how to configure export conditions if the widget is tree-shaken or not found.verifySolution always returns false in serverless or edge deployments
verifySolution always returns false in serverless or edge deployments
Cause: The default
local replay store lives in process memory. In serverless environments each function invocation is a fresh process, so tokens consumed in a previous invocation are unknown to the next one. This causes the in-memory store to treat every submission as its first — but if two concurrent invocations race, both may consume the same token, or neither may hold state long enough to protect against replay.Fix: Switch to replayPrevention: 'remote' with a Redis or Valkey adapter that uses atomic SET NX EX semantics:React wrapper throws an SSR error in Next.js
React wrapper throws an SSR error in Next.js
Cause: The Do not wrap the component with
<ribaunt-widget> web component registers itself using browser-only APIs such as customElements and window. These are not available during server-side rendering.Fix: Add 'use client' at the top of any component file that imports or renders RibauntWidget:next/dynamic — the Ribaunt React wrapper already handles dynamic importing of the browser bundle internally. Adding a second layer of dynamic import can interfere with this mechanism and cause double-loading or hydration mismatches.Enabling debug logging
By default, Ribaunt logs verification warnings to the console whenNODE_ENV is set to development. In other environments, warnings are silent unless you opt in. Use the debug option to enable console output explicitly, or use onWarning for structured logging that works in any environment.
NODE_ENV=development, debug is enabled by default — you don’t need to pass it explicitly during local development. In production, rely on onWarning instead of debug: true to avoid flooding application logs with low-signal noise.