Client SDK for capturing and reporting errors to your Error Ingestor server. Works with React Native (iOS/Android) and web applications.
npm install @error-ingestor/client
# or
pnpm add @error-ingestor/client
# or
yarn add @error-ingestor/clientimport { ErrorIngestor, ErrorBoundary } from '@error-ingestor/client';
// 1. Initialize at app startup
ErrorIngestor.init({
apiKey: 'your-api-key',
appId: 'com.yourcompany.app',
appVersion: '1.0.0',
endpoint: 'https://errors.yourcompany.com',
});
// 2. Wrap your app with ErrorBoundary
export default function App() {
return (
<ErrorBoundary fallback={<ErrorFallback />}>
<MainApp />
</ErrorBoundary>
);
}Initialize the client. Must be called once before capturing errors.
interface ErrorIngestorConfig {
// Required
apiKey: string; // API key from your server
appId: string; // Unique app identifier (e.g., bundle ID)
appVersion: string; // Current app version
endpoint: string; // Error Ingestor server URL
// Optional
userId?: string; // User ID for tracking (can be set later)
batchSize?: number; // Errors per batch (default: 10)
flushInterval?: number; // Auto-flush interval in ms (default: 5000)
maxRetries?: number; // Retry attempts on failure (default: 3)
debug?: boolean; // Enable console logging (default: false)
}
// Example
ErrorIngestor.init({
apiKey: 'ei_abc123',
appId: 'com.example.myapp',
appVersion: '2.1.0',
endpoint: 'https://errors.example.com',
userId: 'user-123',
batchSize: 20,
flushInterval: 10000,
debug: __DEV__, // Enable in development
});Capture an error and queue it for sending.
import { ErrorIngestor, AppError, ErrorCodes } from '@error-ingestor/client';
// Capture a standard Error
try {
await fetchData();
} catch (error) {
ErrorIngestor.capture(error);
}
// Capture with metadata
ErrorIngestor.capture(error, {
metadata: {
userId: 'user-123',
action: 'checkout',
cartItems: 3,
},
tags: {
severity: 'critical',
component: 'PaymentForm',
},
});
// Capture a custom AppError
const error = new AppError(
ErrorCodes.NETWORK_ERROR,
'Failed to connect to payment gateway'
);
ErrorIngestor.capture(error);Set or update the user ID for future errors.
// After user logs in
ErrorIngestor.setUserId('user-456');
// After user logs out
ErrorIngestor.setUserId(null);Force send all queued errors immediately.
// Before app closes or user logs out
await ErrorIngestor.flush();Check if the client is initialized.
if (ErrorIngestor.isReady()) {
ErrorIngestor.capture(error);
}Get the number of errors waiting to be sent.
const pending = ErrorIngestor.getQueueSize();
console.log(`${pending} errors in queue`);Cleanup and flush remaining errors.
// On app shutdown
ErrorIngestor.destroy();A React Error Boundary that automatically captures and reports errors.
import { ErrorBoundary } from '@error-ingestor/client';
// Basic usage
<ErrorBoundary fallback={<ErrorScreen />}>
<App />
</ErrorBoundary>
// With render function (access error and reset)
<ErrorBoundary
fallback={(error, reset) => (
<View>
<Text>Something went wrong: {error.message}</Text>
<Button title="Try Again" onPress={reset} />
</View>
)}
onError={(error, errorInfo) => {
// Additional error handling
console.log('Component stack:', errorInfo.componentStack);
}}
onReset={() => {
// Called when reset() is invoked
navigation.navigate('Home');
}}
>
<App />
</ErrorBoundary>| Prop | Type | Description |
|---|---|---|
children |
ReactNode |
Content to render |
fallback |
ReactNode | (error, reset) => ReactNode |
UI to show on error |
onError |
(error, errorInfo) => void |
Optional error callback |
onReset |
() => void |
Optional reset callback |
Define your own error codes for better categorization.
import { AppError } from '@error-ingestor/client';
// Define custom codes
const MyErrorCodes = {
PAYMENT_FAILED: 'payment/failed',
PAYMENT_TIMEOUT: 'payment/timeout',
CART_EMPTY: 'cart/empty',
INVENTORY_LOW: 'inventory/low-stock',
} as const;
// Use custom codes
const error = new AppError(
MyErrorCodes.PAYMENT_FAILED,
'Credit card was declined'
);
ErrorIngestor.capture(error);import { ErrorCodes } from '@error-ingestor/client';
ErrorCodes.USER_NOT_FOUND // 'auth/user-not-found'
ErrorCodes.USER_NOT_AUTHENTICATED // 'auth/user-not-authenticated'
ErrorCodes.INVALID_CREDENTIALS // 'auth/invalid-credentials'
ErrorCodes.NETWORK_ERROR // 'network/request-failed'
ErrorCodes.TIMEOUT // 'network/timeout'
ErrorCodes.VALIDATION_ERROR // 'validation/invalid-input'
ErrorCodes.UNKNOWN // 'unknown/unhandled'The client works great with neverthrow for type-safe error handling.
import { Result, ok, err } from 'neverthrow';
import { ErrorIngestor, AppError, ErrorCodes } from '@error-ingestor/client';
// Define a function that returns Result
async function fetchUser(id: string): Promise<Result<User, AppError>> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
const error = new AppError(
ErrorCodes.FETCH_FAILED,
`Failed to fetch user: ${response.status}`
);
ErrorIngestor.capture(error);
return err(error);
}
return ok(await response.json());
} catch (e) {
const error = new AppError(ErrorCodes.NETWORK_ERROR, 'Network request failed');
ErrorIngestor.capture(error);
return err(error);
}
}
// Usage
const result = await fetchUser('123');
result
.map(user => {
// Handle success
console.log('User:', user.name);
})
.mapErr(error => {
// Handle error (already captured)
showToast(error.message);
});import type {
ErrorIngestorConfig,
CaptureOptions,
ErrorEvent,
ErrorCode,
} from '@error-ingestor/client';
// CaptureOptions
interface CaptureOptions {
metadata?: Record<string, unknown>;
tags?: Record<string, string>;
userId?: string;
}
// ErrorEvent (what gets sent to the server)
interface ErrorEvent {
id: string;
code: string;
message: string;
stackTrace: string;
appId: string;
appVersion: string;
platform: 'ios' | 'android' | 'web';
platformVersion: string;
userId?: string;
timestamp: string;
metadata?: Record<string, unknown>;
tags?: Record<string, string>;
}| Platform | Supported | Notes |
|---|---|---|
| React Native (iOS) | Yes | Expo and bare workflow |
| React Native (Android) | Yes | Expo and bare workflow |
| Web (React) | Yes | Any React web app |
| Next.js | Yes | Client components only |
| Node.js | Partial | Manual capture only (no ErrorBoundary) |
- Initialize early: Call
init()as soon as possible in your app lifecycle. - Use ErrorBoundary: Wrap your root component to catch React errors automatically.
- Add context: Include relevant metadata (user actions, screen name, etc.).
- Use custom error codes: Create semantic codes for your domain.
- Flush on logout: Call
flush()before clearing user session.
// Example: Full setup in React Native
import { ErrorIngestor, ErrorBoundary } from '@error-ingestor/client';
// Initialize in index.js or App.tsx
ErrorIngestor.init({
apiKey: process.env.ERROR_INGESTOR_API_KEY,
appId: 'com.example.app',
appVersion: require('./package.json').version,
endpoint: process.env.ERROR_INGESTOR_ENDPOINT,
debug: __DEV__,
});
export default function App() {
return (
<ErrorBoundary
fallback={(error, reset) => (
<ErrorScreen error={error} onRetry={reset} />
)}
>
<AuthProvider>
<Navigation />
</AuthProvider>
</ErrorBoundary>
);
}