The Encore SDK provides structured error handling with specific error codes and types. This guide covers all error types and best practices for handling them.
Error Types
EncoreError
All SDK errors conform to this interface:
interface EncoreError {
code : ErrorCode | string
message : string
details ?: unknown
type ?: string
statusCode ?: number
}
Error code identifying the error type. See Error Codes below.
Human-readable error message
Additional error details (if available)
Error type category (if applicable)
HTTP status code (for API errors)
NotGrantedReason
When presentOffer() doesn’t grant an entitlement, the reason can be:
type NotGrantedReason =
| 'userClosedModal'
| 'userClickedOutside'
| 'userDeclinedLastOffer'
| 'noOffersAvailable'
| { type : 'error' , error : EncoreError }
Error Codes
ErrorCode Enum
enum ErrorCode {
// Network errors
NETWORK_ERROR = 'NETWORK_ERROR' ,
TIMEOUT = 'TIMEOUT' ,
// API errors
API_ERROR = 'API_ERROR' ,
UNAUTHORIZED = 'UNAUTHORIZED' ,
NOT_FOUND = 'NOT_FOUND' ,
INVALID_REQUEST = 'INVALID_REQUEST' ,
// Configuration errors
CONFIGURATION_ERROR = 'CONFIGURATION_ERROR' ,
INITIALIZATION_ERROR = 'INITIALIZATION_ERROR' ,
// Storage errors
STORAGE_ERROR = 'STORAGE_ERROR' ,
// Generic
UNKNOWN_ERROR = 'UNKNOWN_ERROR'
}
Error Code Descriptions
When it occurs : Network connectivity issuesCommon causes :
User is offline
DNS resolution failed
Network request blocked by firewall/proxy
Handling :try {
await Encore . refreshEntitlements ();
} catch ( error ) {
if ( error . code === 'NETWORK_ERROR' ) {
showMessage ( 'Please check your internet connection' );
retryLater ();
}
}
When it occurs : Request took too long to completeCommon causes :
Slow network connection
Server overload
Large payload
Handling :try {
await Encore . presentOffer ();
} catch ( error ) {
if ( error . code === 'TIMEOUT' ) {
showMessage ( 'Request timed out. Please try again.' );
logTimeout ( error );
}
}
When it occurs : API returned an error responseCommon causes :
Server-side error
Invalid request format
Rate limiting
Handling :try {
await Encore . refreshEntitlements ();
} catch ( error ) {
if ( error . code === 'API_ERROR' ) {
console . error ( 'API error:' , error . message );
if ( error . statusCode === 429 ) {
showMessage ( 'Too many requests. Please wait.' );
}
}
}
When it occurs : Invalid API key or authentication failedCommon causes :
Wrong API key
Expired API key
Revoked API key
Handling :try {
await Encore . presentOffer ();
} catch ( error ) {
if ( error . code === 'UNAUTHORIZED' ) {
console . error ( 'Invalid API key' );
contactSupport ();
}
}
When it occurs : SDK configuration is invalidCommon causes :
Missing required configuration
Invalid configuration values
Configuration called multiple times
Handling :try {
Encore . configure ({ apiKey: '' }); // Empty key
} catch ( error ) {
if ( error . code === 'CONFIGURATION_ERROR' ) {
console . error ( 'Configuration error:' , error . message );
// Fix configuration
}
}
When it occurs : localStorage/sessionStorage operations failedCommon causes :
Browser privacy settings
Storage quota exceeded
Private/incognito mode restrictions
Handling :try {
Encore . identify ( 'user-123' );
} catch ( error ) {
if ( error . code === 'STORAGE_ERROR' ) {
showMessage ( 'Storage unavailable. Some features may not work.' );
fallbackToSessionStorage ();
}
}
Handling Errors
Try-Catch Pattern
import Encore from '@encore/web-sdk' ;
try {
const result = await Encore . presentOffer ();
if ( result . granted ) {
unlockFeature ();
}
} catch ( error ) {
console . error ( 'Error presenting offer:' , error );
// Handle specific error codes
switch ( error . code ) {
case 'NETWORK_ERROR' :
showMessage ( 'Please check your connection' );
break ;
case 'UNAUTHORIZED' :
contactSupport ();
break ;
default :
showGenericError ();
}
}
Callback Error Handling
await Encore . presentOffer ({
onGranted : ( entitlement ) => {
unlockFeature ();
},
onNotGranted : ( reason ) => {
if ( typeof reason === 'object' && reason . type === 'error' ) {
handleError ( reason . error );
}
},
onError : ( error ) => {
console . error ( 'Presentation error:' , error );
showErrorMessage ( error . message );
}
});
Graceful Degradation
async function safeRefreshEntitlements () {
try {
await Encore . refreshEntitlements ();
} catch ( error ) {
console . error ( 'Refresh failed:' , error );
// Continue without refresh - use cached data
}
}
Common Error Scenarios
Network Errors
async function handleNetworkError () {
try {
await Encore . presentOffer ();
} catch ( error ) {
if ( error . code === 'NETWORK_ERROR' ) {
// Show retry option
showRetryButton (() => handleNetworkError ());
// Queue for later
queueOperation ( 'presentOffer' );
// Use cached data
const cachedData = getCachedEntitlements ();
if ( cachedData ) {
useCachedData ( cachedData );
}
}
}
}
API Errors
async function handleAPIError () {
try {
await Encore . refreshEntitlements ();
} catch ( error ) {
if ( error . code === 'API_ERROR' ) {
// Log for debugging
logError ( error );
// Check status code
if ( error . statusCode === 503 ) {
showMessage ( 'Service temporarily unavailable' );
} else if ( error . statusCode === 429 ) {
showMessage ( 'Too many requests. Please wait.' );
}
// Retry with backoff
retryWithBackoff (() => Encore . refreshEntitlements ());
}
}
}
Configuration Errors
function initializeSDK ( apiKey ) {
try {
Encore . configure ({ apiKey });
} catch ( error ) {
if ( error . code === 'CONFIGURATION_ERROR' ) {
console . error ( 'Configuration failed:' , error . message );
// Show error to developer
if ( process . env . NODE_ENV === 'development' ) {
showDevError ( error );
}
// Fallback to default config
Encore . configure ({ apiKey: process . env . FALLBACK_KEY });
}
}
}
Framework Error Handling
import { useState } from 'react' ;
import Encore from '@encore/web-sdk' ;
function OfferButton () {
const [ error , setError ] = useState ( null );
const [ loading , setLoading ] = useState ( false );
const handleClick = async () => {
setError ( null );
setLoading ( true );
try {
const result = await Encore . presentOffer ();
// Handle success
} catch ( err ) {
setError ( err );
console . error ( 'Error:' , err );
} finally {
setLoading ( false );
}
};
return (
< div >
< button onClick = { handleClick } disabled = { loading } >
Get Premium
</ button >
{ error && (
< div className = "error" >
{ getErrorMessage ( error ) }
</ div >
) }
</ div >
);
}
function getErrorMessage ( error ) {
switch ( error . code ) {
case 'NETWORK_ERROR' :
return 'Connection error. Please try again.' ;
case 'UNAUTHORIZED' :
return 'Authentication failed. Please contact support.' ;
default :
return 'Something went wrong. Please try again.' ;
}
}
Best Practices
1. Always Handle Errors
// Good: Error handling
try {
await Encore . presentOffer ();
} catch ( error ) {
handleError ( error );
}
// Avoid: No error handling
await Encore . presentOffer (); // ❌ Unhandled rejection
2. Provide User Feedback
// Good: User-friendly messages
try {
await Encore . refreshEntitlements ();
} catch ( error ) {
showMessage ( getUserFriendlyMessage ( error ));
}
// Avoid: Technical messages
catch ( error ) {
alert ( error . message ); // ❌ "API_ERROR: 500"
}
3. Log for Debugging
// Good: Comprehensive logging
try {
await Encore . presentOffer ();
} catch ( error ) {
console . error ( 'Error details:' , {
code: error . code ,
message: error . message ,
details: error . details
});
trackError ( error );
}
4. Graceful Degradation
// Good: Continue with cached data
try {
await Encore . refreshEntitlements ();
} catch ( error ) {
console . warn ( 'Using cached entitlements' );
// App continues to work
}
Complete Error Handling Example
import Encore from '@encore/web-sdk' ;
class ErrorHandler {
async presentOfferWithErrorHandling () {
try {
const result = await Encore . presentOffer ();
if ( result . granted ) {
return { success: true , entitlement: result . entitlement };
}
return { success: false , reason: result . reason };
} catch ( error ) {
return this . handleError ( error );
}
}
handleError ( error ) {
// Log error
console . error ( 'Encore error:' , error );
this . trackError ( error );
// Handle specific errors
switch ( error . code ) {
case 'NETWORK_ERROR' :
this . showMessage ( 'Connection error. Please check your internet.' );
return { success: false , error: 'network' };
case 'UNAUTHORIZED' :
this . showMessage ( 'Authentication failed. Please contact support.' );
this . contactSupport ( error );
return { success: false , error: 'auth' };
case 'TIMEOUT' :
this . showMessage ( 'Request timed out. Please try again.' );
return { success: false , error: 'timeout' };
default :
this . showMessage ( 'Something went wrong. Please try again.' );
return { success: false , error: 'unknown' };
}
}
showMessage ( message ) {
// Show user-friendly message
console . log ( message );
}
trackError ( error ) {
// Send to analytics/monitoring
if ( window . analytics ) {
analytics . track ( 'encore_error' , {
code: error . code ,
message: error . message
});
}
}
contactSupport ( error ) {
// Notify support team
console . error ( 'Critical error:' , error );
}
}
Next Steps