These happen synchronously in the Keyset constructor — wrap in try/catch or fix the config.
| Condition | Error message |
|---|---|
apiKey is empty | "API key is required" |
Key doesn't start with pkey_ or skey_ | "Invalid API key format" |
TypeScripttry { const client = new Keyset({ apiKey: "", cacheTTL: 0 }); } catch (err) { console.error(err.message); // "API key is required" }
Calling a write method (create, update, delete, dashboardList) with a public key (pkey_…) throws synchronously before any network call:
TypeScript// Client created with a public key const client = new Keyset({ apiKey: "pkey_abc", cacheTTL: 0 }); try { await client.content.create({ key: "x", value: 1, type: "number" }); } catch (err) { console.error(err.message); // "This operation requires a secret key" }
The HttpClient throws an Error when:
response.data.error if present, otherwise "Request failed"timeout — the browser's AbortController fires and throws an AbortErrorTypeScripttry { const data = await client.content.getAll(); } catch (err) { if (err.name === "AbortError") { console.error("Request timed out"); } else { console.error("Request failed:", err.message); } }
When retries > 0, the SDK re-attempts failed requests up to that many times before throwing. Between retries it waits using exponential backoff:
delay = 2^attempt × 100 ms
| Attempt | Delay |
|---|---|
| 1st retry | 200 ms |
| 2nd retry | 400 ms |
| 3rd retry | 800 ms |
TypeScriptconst client = new Keyset({ apiKey: "pkey_abc", cacheTTL: 0, retries: 3, // retry up to 3 times timeout: 8000, });
The error is only thrown after all retry attempts are exhausted.
useContent catches errors internally and surfaces them in the error state field — it never throws in render. Always check error before using data:
TypeScript JSXconst { data, loading, error } = useContent(); if (loading) return <Spinner />; if (error) return <ErrorBanner message={error} />; return <Dashboard data={data} />;
The typed hooks (useKeysetString, useKeysetBoolean, etc.) silently return defaultValue when a key is missing or has the wrong type. They do not expose an error field — if you need error visibility, use useContent or useContentKey instead.
VITE_*, NEXT_PUBLIC_*) are visible to anyone. Secret keys must only live in server-side code.retries: 2 or retries: 3 provides resilience against transient network failures.defaultValue — always pass a sensible default to the typed getters so your app degrades gracefully if a key hasn't been created yet in Keyset.