Skip to main content

Error Reference

The script is designed to never break your page — all errors are caught internally and logged to console.error. However, certain failure conditions produce observable symptoms. This page documents every error by subsystem.

About the error codes

The ERR_* identifiers below are documentation labels — they are not exported constants or typed error codes in the script. Errors are thrown as plain Error objects with the message strings shown. You cannot catch or match on ERR_IFRAME_TIMEOUT directly; match on the .message string instead.


General Error-Handling Pattern

// Listen for initialization failures (the only error surfaced as a DOM event)
window.addEventListener('opportify:init-failed', (event) => {
const { attempts, error } = event.detail;
// Log, fall back to an alternate form handler, or notify your monitoring system
console.error(`Opportify failed after ${attempts} attempts: ${error}`);
});

For API errors, the script logs to console.error internally. Add a console.error override in non-production environments to capture these if needed.


Initialization Errors

Errors that occur during POST /intel/v1/init or before it can be sent.


ERR_IFRAME_TIMEOUT

PropertyValue
WhenThe bridge iframe does not respond within ~1 second of page load
MessageIframe Bridge failed to respond after 1 second. Ensure the bridge iframe is accessible and not blocked by CSP or network issues.
Surfaced asopportify:init-failed DOM event after 3 retry attempts

Root causes:

  • frame-src CSP directive blocks cdn.opportify.ai
  • Network request to CDN blocked (ad-blocker, firewall, offline)
  • document.body not yet available when the script runs (very rare edge case)

Fix:

Content-Security-Policy: frame-src 'self' https://cdn.opportify.ai;

Verify the iframe is present:

document.getElementById('opportify-bridge-iframe') // should not be null

ERR_INIT_MISSING_FIELDS

PropertyValue
WhenThe API returns HTTP 200 but the response body is missing clientId, sessionId, or nonce
MessageInit response is missing required fields
Surfaced asopportify:init-failed after retries

Root causes:

  • API version mismatch
  • Malformed response from a proxy or CDN layer in front of api.opportify.ai

Fix: Check network traffic for the /intel/v1/init response body. If you use a reverse proxy, ensure it passes the response body through unmodified.


ERR_INIT_HTTP

PropertyValue
WhenPOST /intel/v1/init returns a non-2xx HTTP status
MessageInit request failed with status {status}
Surfaced asconsole.error + opportify:init-failed after retries
StatusLikely cause
400Request payload is malformed; the script automatically retries without the platform field
401Invalid or expired public key
403Domain not allowlisted in the Admin Console
429Rate limit exceeded
5xxOpportify API unavailable

Fix by status:

// 401/403 — check your key and allowlist
// Admin Console → Settings → API Keys
// Admin Console → Quick Start → Step 1 (Allowlist domain)

// 429 — reduce page load frequency or contact support
// 5xx — transient; the script retries with exponential back-off (1s, 2s, 4s)

ERR_NO_PUBLIC_KEY

PropertyValue
WhenNo data-opportify-key attribute found on the script tag at startup
BehaviorScript silently no-ops — no init request is made, no forms are instrumented

Fix:

<script
src="https://cdn.opportify.ai/f/v0.4.3.min.js"
data-opportify-key="pk_live_YOUR_KEY"
async
></script>

Token Minting Errors

Errors from POST /intel/v1/forms/tokens (dynamic form token minting).


ERR_MINT_MISSING_SESSION

PropertyValue
WhenmintFormTokens is called before init has completed (i.e. clientId, sessionId, or nonce is missing)
MessageclientId, sessionId, and nonce are required for token minting
Surfaced asThrown Error — caught internally, logged to console.error

Root cause: A form was detected by MutationObserver before the init response was received. The script serializes init before token minting, so this should not occur under normal conditions.

Fix: Ensure forms are not rendered to the DOM until after DOMContentLoaded. If you must render forms immediately, use window.FormWatcher.initForm(form) after the opportify:init-failed event confirms init either succeeded or failed.


ERR_MINT_HTTP

PropertyValue
WhenPOST /intel/v1/forms/tokens returns a non-2xx status
MessageToken minting request failed with status {status}
Surfaced asconsole.error

Result: The affected form will have an empty opportifyToken. Submissions from that form will be flagged as untrusted by the backend.


Form Submission Errors

Errors from POST /intel/v1/submit/{endpointId}.


ERR_SUBMIT_MISSING_ENDPOINT

PropertyValue
WhensubmitForm is called with an empty endpointId
MessageendpointId is required for form submission
Surfaced asThrown Error

Root cause: The form's action URL does not end with a recognizable endpoint ID (UUID-like last path segment).

Fix:

<!-- Correct -->
<form action="https://api.opportify.ai/intel/v1/submit/3f2504e0-4f89-11d3-9a0c-0305e82c3301">

<!-- Wrong — no endpoint ID -->
<form action="https://api.opportify.ai/intel/v1/submit/">

ERR_SUBMIT_MISSING_TOKEN

PropertyValue
WhensubmitForm is called with an empty opportifyToken
MessageopportifyToken is required for form submission
Surfaced asThrown Error

Root cause: The opportifyToken hidden field was not injected (init didn't complete) or was manually removed from the DOM.

Fix: Ensure the script initializes before the user submits. Listen for opportify:init-failed and disable the submit button if init does not complete:

window.addEventListener('opportify:init-failed', () => {
document.querySelectorAll('button[type="submit"]').forEach((btn) => {
btn.setAttribute('title', 'Submission temporarily unavailable');
});
});

ERR_SUBMIT_HTTP

PropertyValue
WhenPOST /intel/v1/submit/{endpointId} returns a non-2xx status
MessageForm submission failed with status {status}
Surfaced asThrown Error — propagates to the submit handler
StatusMeaning
400Malformed payload or missing required fields
401Invalid or mismatched opportifyToken
404Endpoint ID not found — check the UUID in action
429Rate limit exceeded for this endpoint
5xxOpportify API unavailable

Response shape on error:

{
"errorCode": "INVALID_TOKEN",
"errorMessage": "The provided opportifyToken is invalid or has expired."
}

Error handling example:

try {
const response = await fetch(
'https://api.opportify.ai/intel/v1/submit/YOUR_ENDPOINT_ID',
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }
);

if (!response.ok) {
const err = await response.json();
console.error(`Submission error [${err.errorCode}]: ${err.errorMessage}`);
// Show user-facing error
return;
}

const result = await response.json();
// result.accepted === true on success
if (!result.accepted) {
// Submission was received but not accepted (e.g. flagged as high-risk)
showErrorMessage('Your submission could not be processed.');
} else {
showSuccessMessage('Submitted successfully!');
}
} catch (networkError) {
console.error('Network error during form submission:', networkError);
}

Telemetry Errors

Errors from POST /intel/v1/events.


ERR_EVENTS_MISSING_SESSION

PropertyValue
WhensendEvents is called before init has completed
MessageclientId, sessionId, and nonce are required for telemetry
Surfaced asThrown Error — caught internally

Root cause: Telemetry is only sent after init completes successfully. This error indicates a programming error — sendEvents was called from outside the normal script lifecycle.


ERR_EVENTS_HTTP

PropertyValue
WhenPOST /intel/v1/events returns a non-2xx status
MessageEvents request failed with status {status}
Surfaced asconsole.error; the script continues operating

Telemetry failures are non-fatal. The script continues to instrument forms and process submissions even if telemetry delivery fails.


Crypto Errors

Errors from the Web Crypto API utilities.


ERR_CRYPTO_UNAVAILABLE

PropertyValue
WhenglobalThis.crypto.subtle is not available
MessageWeb Crypto API is not available
Surfaced asThrown Error from sha256Hex / hmacSha256Hex

Root cause: The page is served over http:// (non-secure context) in a browser that restricts Web Crypto to secure origins, or the browser is extremely old.

Fix: Serve your page over https://. Web Crypto requires a secure context.


ERR_INVALID_NONCE_HEX

PropertyValue
WhenobfuscateJsonWithNonce receives a nonce that is not valid hex
MessageInvalid hex string
Surfaced asThrown Error

Root cause: The nonce returned by the API was corrupted in transit or by a proxy stripping characters.


Quick Reference Table

ErrorSubsystemFatal?User-visible?
ERR_IFRAME_TIMEOUTInitNoopportify:init-failed event
ERR_INIT_MISSING_FIELDSInitNoopportify:init-failed event
ERR_INIT_HTTPInitNoopportify:init-failed event
ERR_NO_PUBLIC_KEYInitYes (silent no-op)No
ERR_MINT_MISSING_SESSIONToken MintingNoNo (console only)
ERR_MINT_HTTPToken MintingNoNo (console only)
ERR_SUBMIT_MISSING_ENDPOINTSubmissionNoForm stays on page
ERR_SUBMIT_MISSING_TOKENSubmissionNoForm stays on page
ERR_SUBMIT_HTTPSubmissionNoForm stays on page
ERR_EVENTS_MISSING_SESSIONTelemetryNoNo
ERR_EVENTS_HTTPTelemetryNoNo
ERR_CRYPTO_UNAVAILABLECryptoYes (init fails)opportify:init-failed
ERR_INVALID_NONCE_HEXCryptoNo (events fail)No