Skip to main content

Error Handling

React Achievements routes achievement and storage errors through AchievementProvider.onError and engine error events.

Error Callback​

Handle achievement errors once at the provider boundary:

import {
AchievementProvider,
isAchievementError,
isRecoverableError,
} from 'react-achievements';

<AchievementProvider
achievements={achievements}
onError={(error) => {
if (isAchievementError(error)) {
console.error(error.code, error.message);
console.info(error.remedy);
}

if (!isRecoverableError(error)) {
reportToMonitoring(error);
}
}}
>
<YourApp />
</AchievementProvider>

Error Classes​

All built-in achievement errors extend AchievementError.

import {
AchievementError,
ConfigurationError,
ImportValidationError,
StorageError,
StorageQuotaError,
SyncError,
} from 'react-achievements';

AchievementError​

Base class for achievement-specific failures.

error.code;        // string machine-readable code
error.recoverable; // boolean
error.remedy; // optional recovery guidance

StorageQuotaError​

Raised when browser storage does not have enough space.

onError={(error) => {
if (error instanceof StorageQuotaError) {
console.warn(`Need ${error.bytesNeeded} more bytes`);
}
}}

StorageError​

Raised when a storage adapter fails outside quota handling.

onError={(error) => {
if (error instanceof StorageError) {
console.error(error.originalError || error);
}
}}

ConfigurationError​

Raised when achievement configuration cannot be normalized or evaluated.

onError={(error) => {
if (error instanceof ConfigurationError) {
console.error('Invalid achievement configuration:', error.message);
}
}}

ImportValidationError​

Raised when imported achievement data fails validation.

onError={(error) => {
if (error instanceof ImportValidationError) {
console.error(error.validationErrors);
}
}}

SyncError​

Raised by network-backed storage when sync fails.

onError={(error) => {
if (error instanceof SyncError) {
console.error(error.statusCode, error.timeout);
}
}}

Storage Recovery​

For most apps, choose a durable storage option up front and keep a memory fallback for unrecoverable browser storage failures:

import { useState } from 'react';
import {
AchievementProvider,
StorageError,
StorageQuotaError,
StorageType,
} from 'react-achievements';

function AppWithFallback() {
const [storage, setStorage] = useState(StorageType.Local);

return (
<AchievementProvider
achievements={achievements}
storage={storage}
onError={(error) => {
if (error instanceof StorageQuotaError || error instanceof StorageError) {
setStorage(StorageType.Memory);
}
}}
>
<YourApp />
</AchievementProvider>
);
}

Use StorageType.IndexedDB for larger browser datasets:

<AchievementProvider achievements={achievements} storage={StorageType.IndexedDB}>
<YourApp />
</AchievementProvider>

Use REST API storage when achievement state belongs on your backend:

<AchievementProvider
achievements={achievements}
storage={StorageType.RestAPI}
restApiConfig={{
baseUrl: '/api/achievements',
userId,
headers: { Authorization: `Bearer ${token}` },
}}
>
<YourApp />
</AchievementProvider>

For offline retry behavior, wrap an async storage implementation with OfflineQueueStorage and pass the wrapper as storage.

Engine Error Events​

When using an injected AchievementEngine, you can also subscribe to engine errors:

import { useEffect } from 'react';
import { useAchievementEngine } from 'react-achievements';

function AchievementErrorReporter() {
const engine = useAchievementEngine();

useEffect(() => {
return engine.on('error', (event) => {
console.error(event.error, event.context);
});
}, [engine]);

return null;
}

Common Checks​

If an achievement is not unlocking, inspect the current state through hooks instead of relying on provider debug props:

const { metrics, allAchievements, unlockedIds } = useSimpleAchievements();

console.log(metrics);
console.log(allAchievements);
console.log(unlockedIds);

Check that:

  • The component using hooks is inside AchievementProvider
  • The metric name in track, increment, or event mapping matches the config
  • Numeric, boolean, and string threshold values match the tracked value type
  • Custom condition functions return true for the current metrics
  • The storage adapter returns arrays for metrics and unlocked achievement IDs

What's Next?​