Error Handling & Caching
The SDK is designed so that a VersionR outage never crashes your application.
VersionRError
All SDK errors are instances of VersionRError, which extends the native Error class with a code field:
import { VersionRError } from 'versionr'
try {
const prompt = await pd.get('my-prompt', { env: 'production' })
} catch (err) {
if (err instanceof VersionRError) {
console.error(err.code) // e.g. "NO_ACTIVE_VERSION"
console.error(err.message) // human-readable description
}
}Error codes
| Code | Cause |
|---|---|
NO_ACTIVE_VERSION | The environment has no deployed version for this prompt |
PROMPT_NOT_FOUND | No prompt exists with this slug |
MISSING_VARIABLE | A required variable was not provided to pd.render() |
AUTH_FAILED | Invalid or missing API key |
NETWORK_ERROR | Request to the VersionR API failed |
TIMEOUT | Request exceeded the configured timeout |
In-memory caching
The SDK keeps an in-memory cache of every prompt it has successfully fetched. This cache persists for the lifetime of the process.
On a successful fetch — the response is stored in the cache, keyed by slug + environment.
On a failed fetch — if a cached version exists, it is returned silently. Your app receives the last-known-good prompt and continues normally.
// First call — hits the API, stores in cache
const prompt = await pd.get('interviewer-system', { env: 'production' })
// Subsequent calls — served from cache if API is unreachable
const prompt = await pd.get('interviewer-system', { env: 'production' })The in-memory cache does not persist across process restarts. Cold-start deployments (serverless, edge) will always hit the API on first invocation.
Disabling the cache
If you need to disable the fallback cache (e.g. for testing), pass cache: false during initialisation:
const pd = new VersionR({
apiKey: process.env.VERSIONR_API_KEY,
cache: false,
})With the cache disabled, any fetch failure throws a VersionRError immediately.
Retries
The SDK automatically retries failed requests once before falling back to the cache or throwing. This handles transient network blips without any configuration.
There is currently no built-in exponential backoff — if you need more aggressive retry behaviour, wrap SDK calls in your own retry logic.
Timeouts
The default request timeout is 5000 ms. Override it during initialisation:
const pd = new VersionR({
apiKey: process.env.VERSIONR_API_KEY,
timeout: 2000, // 2 seconds
})If the request times out and a cached version exists, it is returned. Otherwise a VersionRError with code TIMEOUT is thrown.
Recommended pattern
try {
const rendered = await pd.render('my-prompt', {
env: 'production',
variables: { name: 'Eoin' },
})
// use rendered.content
} catch (err) {
if (err instanceof VersionRError && err.code === 'MISSING_VARIABLE') {
// This is a code bug — re-throw so it surfaces immediately
throw err
}
// All other errors: log and use a hardcoded fallback
console.error('VersionR unavailable, using fallback', err)
const content = FALLBACK_PROMPTS['my-prompt']
}Only MISSING_VARIABLE errors warrant re-throwing — they indicate a mismatch between your code and the prompt definition that must be fixed. Network and version errors should be handled gracefully.