Error Tracking
Global error handlers
Section titled “Global error handlers”The SDK can automatically catch uncaught exceptions and unhandled promise rejections, logging them as fatal.
Browser (@gunsole/web — attached automatically):
window.onerror→ logs to bucketglobal_errorwindow.onunhandledrejection→ logs to bucketunhandled_rejection
Node.js (@gunsole/core — attach manually):
process.uncaughtException→ logs to bucketuncaught_exceptionprocess.unhandledRejection→ logs to bucketunhandled_rejection
// @gunsole/core — manual attachmentgunsole.attachGlobalErrorHandlers();
// Detach when done (e.g., in tests)gunsole.detachGlobalErrorHandlers();
// @gunsole/web — automatically attached on createGunsoleClient()Framework error boundaries
Section titled “Framework error boundaries”componentDidCatch(error: Error, info: React.ErrorInfo) { gunsole.fatal({ bucket: "error_boundary", message: error.message, context: { stack: error.stack, componentStack: info.componentStack }, });}Next.js (error.tsx)
Section titled “Next.js (error.tsx)”useEffect(() => { gunsole.fatal({ bucket: "fatal", message: error.message, context: { name: error.name, stack: error.stack, digest: (error as any).digest }, });}, [error]);Angular (ErrorHandler provider)
Section titled “Angular (ErrorHandler provider)”class GunsoleErrorHandler implements ErrorHandler { handleError(error: unknown): void { const err = error instanceof Error ? error : new Error(String(error)); gunsole.fatal({ bucket: "fatal", message: err.message, context: { name: err.name, stack: err.stack } }); }}Solid.js
Section titled “Solid.js”<ErrorBoundary fallback={(err) => { gunsole.fatal({ bucket: "fatal", message: err instanceof Error ? err.message : String(err) }); return <div>Error</div>;}}>Manual error logging
Section titled “Manual error logging”For errors you catch yourself:
try { await riskyOperation();} catch (err) { gunsole.error({ bucket: "api", message: `Operation failed: ${err.message}`, context: { error: err.message, stack: err.stack, code: err.code, }, tags: { operation: "riskyOperation", errorType: err.constructor.name, }, });}HTTP interceptors
Section titled “HTTP interceptors”Fetch wrapper
Section titled “Fetch wrapper”const originalFetch = window.fetch;window.fetch = async (...args) => { try { const response = await originalFetch(...args); if (!response.ok) { gunsole.error({ bucket: "http", message: `HTTP ${response.status}: ${args[0]}`, context: { status: response.status, url: String(args[0]) }, tags: { status: String(response.status) }, }); } return response; } catch (err) { gunsole.error({ bucket: "http", message: `Network error: ${args[0]}`, context: { error: err instanceof Error ? err.message : String(err), url: String(args[0]) }, }); throw err; }};axios.interceptors.response.use( (response) => response, (error) => { gunsole.error({ bucket: "http", message: `HTTP ${error.response?.status || "network"}: ${error.config.url}`, context: { url: error.config.url, method: error.config.method, status: error.response?.status, data: error.response?.data, }, tags: { status: String(error.response?.status || "network_error"), method: error.config.method.toUpperCase(), }, }); return Promise.reject(error); });Pattern: error tags
Section titled “Pattern: error tags”Use consistent tags for errors so you can filter by error type in the desktop app:
gunsole.error({ bucket: "api", message: "Payment failed", tags: { error_type: "validation", // validation, auth, network, timeout, unknown severity: "high", // low, medium, high, critical recoverable: "false", // true, false }, context: { code: "card_declined", provider: "stripe" },});