Errors
Error classes, operation codes and diagnostics of the Web SDK, with what to do for each.
The Web SDK rejects with VoidhashError subclasses, and only for programmer errors and operations
that failed outright. The network never makes a method reject: events and identity writes are
queued and retried, and problems arrive as diagnostics.
Handle errors
Branch on the class with instanceof. A failed operation's message starts with a stable code, such
as FAILED_TO_IDENTIFY.
import { VoidhashInvalidArgumentError, VoidhashNotInitializedError } from "@voidhash/web";
try {
await voidhash.identify("user_123");
} catch (error) {
if (error instanceof VoidhashInvalidArgumentError) {
// The ID is blank or anonymous. Nothing changed.
} else if (error instanceof VoidhashNotInitializedError) {
// Call initialize() first.
} else {
reportError(error); // A VoidhashError whose message starts with FAILED_TO_IDENTIFY.
}
}Background work, such as a scheduled flush, reports through diagnostics and the client's error
event instead.
Error types
All are exported from @voidhash/web and extend VoidhashError.
| Class | Raised when |
|---|---|
VoidhashConfigurationError | createVoidhashClient got an invalid option. |
VoidhashInvalidArgumentError | A method got an argument it can't use. Nothing was changed or sent. |
VoidhashNotInitializedError | A method ran before initialize(). |
VoidhashDestroyedError | A method ran after destroy(). |
VoidhashFeatureFlagsError | useFeatureFlags() sets it as error when loading flags failed with a value that isn't an Error. |
VoidhashError | An operation failed. The message starts with its code, and cause holds the original error. |
Error codes
The code column holds the class for programmer errors, and the message prefix for failed operations. The Web SDK sells no products and presents no paywalls, so it has no purchase or paywall codes; Stripe reports checkout errors (see Checkouts).
Configuration
| Code | When | What to do |
|---|---|---|
VoidhashConfigurationError | An option is invalid: no publishableKey, a secret key (vh_sk_...), a relative baseUrl, an unknown analyticsConsent, or a number that isn't a positive integer. | Fix the option. Rotate a secret key that reached the browser. |
VoidhashNotInitializedError | A method ran before initialize() was called. Calls made while it runs wait for it. | Call initialize() first, or use the provider. |
VoidhashDestroyedError | The client was destroyed, for example by a provider that unmounted. | Create a new client. |
initialize() needs a browser | initialize() ran on a server. | Call it from client-side code, such as an effect, or render the provider. |
FAILED_TO_INITIALIZE | initialize() couldn't load saved state, for example because storage is blocked. | Call initialize() again; with the provider, use retryInit(). |
useVoidhash must be used within a VoidhashProvider | A hook rendered outside the provider. | Wrap the tree in VoidhashProvider. |
FAILED_TO_SET_ANALYTICS_CONSENT | setAnalyticsConsent() got a value other than granted, denied or pending, or couldn't apply it. | Pass a valid value. |
Identity
| Code | When | What to do |
|---|---|---|
VoidhashInvalidArgumentError | identify() got a blank user ID or one starting with vh_anon_ or vh:anon:, or track() a blank event name. | Fix the call. |
FAILED_TO_IDENTIFY | identify() couldn't switch the identity on the device. | Report the error. |
FAILED_TO_SIGN_OUT, FAILED_TO_RESET | signOut() or reset() failed. | Retry. |
FAILED_TO_SET_PERSON_ATTRIBUTES | setPersonAttributes() couldn't queue the update. | Retry. |
FAILED_TO_SET_PERSON_ATTRIBUTES_SYNC | setPersonAttributesSync() didn't get Voidhash's answer, or Voidhash refused the write. | Retry, or use setPersonAttributes(), which queues. |
FAILED_TO_SET_AD_DATA_SHARING | setAdDataSharing() couldn't record the choice. | Retry. |
FAILED_TO_GET_FEATURE_FLAGS, FAILED_TO_REFRESH_FEATURE_FLAGS | Flags couldn't be read or refreshed. | Use your defaults. |
FAILED_TO_TRACK | track() or page() couldn't queue the event. | Report the error. |
FAILED_TO_FLUSH_ANALYTICS, FAILED_TO_FLUSH_IDENTITY | flushAnalytics() failed outright. Transport failures resolve with pending instead. | Nothing. What's queued stays queued. |
Diagnostics
Diagnostics report problems the SDK handled itself, including an unreachable Voidhash
(TRANSPORT_FAILED, CIRCUIT_OPENED) and a rejected publishable key (AUTHENTICATION_FAILED).
Receive them with the onDiagnostic option or client.onDiagnostic(handler):
import { createVoidhashClient } from "@voidhash/web";
const voidhash = createVoidhashClient({
onDiagnostic: (diagnostic) => console.debug("[voidhash]", diagnostic),
publishableKey: "vh_pk_...",
});Each diagnostic has a stable code, a kind for routing, the SDK operation, whether the SDK
will retry (retryable), the httpStatus when there was a response, and a readable message.
| Code | Kind | Meaning |
|---|---|---|
TRANSPORT_FAILED | transport | A request failed or timed out. Events and identity writes are retried. |
ANALYTICS_UNEXPECTED_STATUS | transport | Voidhash answered with an unexpected status. The batch stays queued. |
MALFORMED_CAPTURE_RESPONSE | transport | Voidhash accepted a batch but its answer couldn't be read. |
KEEPALIVE_EVENT_TOO_LARGE | transport | An event didn't fit the request sent while leaving the page. It's sent on the next visit. |
KEEPALIVE_UNCONFIRMED | transport | A closed page sent events while leaving and couldn't see the answer. They count as delivered. |
IDENTITY_WRITE_REFUSED | transport | Voidhash refused an identity link or a setAdDataSharing(false) for good. It was dropped; the browser keeps its identity. |
IDENTITY_WRITE_DROPPED | eviction | More than 20 users identified while Voidhash couldn't be reached; the oldest link was dropped. |
ANALYTICS_EVENT_DROPPED | eviction | Events were dropped: the queue was full, Voidhash refused them for good, or the page closed with events kept in memory past the storage budget. A full queue reports once a minute. |
BEFORE_SEND_FAILED | eviction | analytics.beforeSend threw or returned something other than an event or null, so the event was dropped. |
SANITIZE_URL_FAILED | eviction | analytics.sanitizeUrl threw, so the address wasn't recorded. |
AD_DATA_SHARING_REVOCATION_DROPPED | eviction | A setAdDataSharing(false) was dropped: Voidhash had no such person for 48 hours, or more than 20 were waiting. |
CIRCUIT_OPENED | breaker | Five requests in a row failed, timed out, or got a 408, 425, 5xx or an error page not from Voidhash, so requests pause. They resume on their own. |
CIRCUIT_OPEN | breaker | A request was skipped while requests are paused. |
AUTHENTICATION_FAILED | auth | The publishable key was rejected. Requests pause until initialize(), identify(), signOut() or reset(); otherwise one request retries the key once a minute. |
SHARED_ID_COOKIE_REFUSED | cache | The browser refused the crossSubdomainIdentity cookie, so the anonymous ID isn't shared. Reported once per client. |
CACHE_READ_FAILED | cache | A stored value couldn't be read, for example because it was changed by hand. It was discarded. |
CACHE_WRITE_FAILED | cache | Browser storage refused a write, for example when full. The rest waits in memory. |
ANALYTICS_QUEUE_IN_MEMORY | cache | The queue reached its share of browser storage during an outage. Its oldest events wait in memory and are lost if the page closes first. |
ANALYTICS_CONSENT_DENIED | consent | Analytics consent isn't granted, so analytics aren't recorded. Reported once. |
Report auth diagnostics to your monitoring: they mean no data reaches Voidhash. When
beforeSend or sanitizeUrl throws, the client's error event carries what it threw.
Next steps
- Troubleshooting by symptom.
- Web SDK reference.
- Error codes across platforms.
Something wrong or missing on this page? Tell us by email or on Discord.