The vij-sdk provides two main APIs for capturing errors and messages: captureException() for error objects and captureMessage() for custom log messages.
captureException()
Capture and send error objects to your VIJ Admin dashboard.
Basic Usage
import { captureException } from "vij-sdk" ;
try {
// Code that might throw an error
const result = riskyOperation ();
} catch ( error ) {
captureException ( error );
}
Signature
captureException (
error : Error ,
metadata ?: Record < string , any > ,
severity ?: "error" | "warning" | "info"
): void
Parameters
The error object to capture. Can be any JavaScript Error instance or object with name, message, and stack properties. Supported Types :
Native JavaScript errors (Error, TypeError, ReferenceError, etc.)
Custom error classes extending Error
Objects with error-like structure
// Native error
captureException ( new Error ( "Something went wrong" ));
// Custom error class
class ValidationError extends Error {
constructor ( message ) {
super ( message );
this . name = "ValidationError" ;
}
}
captureException ( new ValidationError ( "Invalid email format" ));
// Error from catch block
try {
await fetchData ();
} catch ( error ) {
captureException ( error );
}
Additional contextual information to attach to this specific error. Use Cases :
User information (ID, email, role)
Request details (URL, method, headers)
Application state at time of error
Feature or component context
captureException ( error , {
userId: "user-123" ,
userEmail: "user@example.com" ,
feature: "checkout" ,
cartTotal: 99.99 ,
requestUrl: "/api/payment" ,
requestMethod: "POST"
});
Metadata is merged with global metadata from init(). Per-error metadata takes precedence.
The severity level of this error. Options :
"error" - Critical errors requiring immediate attention
"warning" - Non-critical issues that should be investigated
"info" - Informational logs for tracking behavior
// Critical error
captureException ( error , { feature: "payment" }, "error" );
// Non-critical warning
captureException ( deprecationError , { api: "legacy" }, "warning" );
// Informational
captureException ( new Error ( "Rate limit approaching" ), {}, "info" );
Severity levels help you filter and prioritize errors in the dashboard.
Automatic Error Capture
The SDK automatically captures uncaught errors and unhandled promise rejections without any additional code:
// Automatically captured - no try/catch needed
window . addEventListener ( "click" , () => {
throw new Error ( "Button click error" ); // Captured automatically
});
// Unhandled promise rejection - automatically captured
fetch ( "/api/data" ). then ( response => {
throw new Error ( "Processing failed" ); // Captured automatically
});
Browser Events Captured :
window.onerror - Uncaught exceptions
window.onunhandledrejection - Unhandled promise rejections
While automatic capture is convenient, it’s better to explicitly catch and handle errors in production code. Use captureException() in catch blocks for better control.
Advanced Examples
import { captureException } from "vij-sdk" ;
async function processPayment ( userId , amount ) {
try {
const payment = await stripeAPI . charge ({ userId , amount });
return payment ;
} catch ( error ) {
captureException ( error , {
// User context
userId: userId ,
userPlan: "premium" ,
// Transaction context
paymentAmount: amount ,
currency: "USD" ,
// Application state
cartItems: 5 ,
discountApplied: true ,
// Technical details
stripeApiVersion: "2023-10-16" ,
timestamp: new Date (). toISOString ()
});
throw error ; // Re-throw after capturing
}
}
Capturing Errors in React Components
import { captureException } from "vij-sdk" ;
import { Component } from "react" ;
class ErrorBoundary extends Component {
componentDidCatch ( error , errorInfo ) {
captureException ( error , {
componentStack: errorInfo . componentStack ,
route: window . location . pathname ,
userAgent: navigator . userAgent
});
}
render () {
return this . props . children ;
}
}
Capturing Errors in Express Middleware
import { captureException } from "vij-sdk" ;
app . use (( err , req , res , next ) => {
captureException ( err , {
requestUrl: req . originalUrl ,
requestMethod: req . method ,
requestHeaders: req . headers ,
requestBody: req . body ,
userId: req . user ?. id ,
ipAddress: req . ip
});
res . status ( 500 ). json ({ error: "Internal server error" });
});
captureMessage()
Capture custom log messages without an error object.
Basic Usage
import { captureMessage } from "vij-sdk" ;
captureMessage ( "User logged in successfully" );
Signature
captureMessage (
message : string ,
metadata ?: Record < string , any > ,
severity ?: "error" | "warning" | "info"
): void
Parameters
The log message to capture. Best Practices :
Use clear, descriptive messages
Include relevant details in the message or metadata
Keep messages concise but informative
// Good
captureMessage ( "Payment processed successfully for order #12345" );
// Better - use metadata
captureMessage ( "Payment processed successfully" , { orderId: 12345 });
Additional contextual information to attach to this message. captureMessage ( "User action" , {
action: "button_click" ,
buttonId: "checkout" ,
userId: "user-123" ,
timestamp: Date . now ()
});
The severity level of this message. Options :
"info" - Informational messages (default for captureMessage)
"warning" - Warning messages
"error" - Error messages
// Info level (default)
captureMessage ( "User logged in" , { userId: "123" }, "info" );
// Warning level
captureMessage ( "Rate limit approaching" , { requestCount: 950 }, "warning" );
// Error level
captureMessage ( "Configuration missing" , { key: "API_KEY" }, "error" );
Use Cases
User Actions
System Events
Performance Monitoring
Business Logic
import { captureMessage } from "vij-sdk" ;
function trackUserAction ( action , details ) {
captureMessage ( `User action: ${ action } ` , {
userId: details . userId ,
actionType: action ,
timestamp: new Date (). toISOString (),
... details
}, "info" );
}
// Track button clicks
trackUserAction ( "checkout_clicked" , {
userId: "user-123" ,
cartValue: 99.99
});
// Track form submissions
trackUserAction ( "form_submitted" , {
formId: "contact-form" ,
fields: 5
});
Contextual Information
Both captureException() and captureMessage() automatically collect rich contextual information:
Browser Context
{
"viewport" : {
"width" : 1920 ,
"height" : 1080
},
"screen" : {
"width" : 1920 ,
"height" : 1080 ,
"colorDepth" : 24
},
"browser" : {
"userAgent" : "Mozilla/5.0..." ,
"language" : "en-US" ,
"platform" : "MacIntel" ,
"cookieEnabled" : true ,
"doNotTrack" : "1"
},
"network" : {
"effectiveType" : "4g" ,
"downlink" : 10 ,
"rtt" : 50
}
}
Node.js Context
{
"process" : {
"pid" : 12345 ,
"platform" : "linux" ,
"arch" : "x64" ,
"nodeVersion" : "v20.0.0" ,
"uptime" : 3600 ,
"memory" : {
"rss" : 50000000 ,
"heapTotal" : 30000000 ,
"heapUsed" : 20000000 ,
"external" : 1000000
}
}
}
This context is collected automatically. You don’t need to add it manually.
Best Practices
Always include relevant metadata
Use appropriate severity levels
Error : Critical issues requiring immediate attentioncaptureException ( paymentError , { orderId: 123 }, "error" );
Warning : Issues that should be investigated but aren’t criticalcaptureException ( deprecatedApiWarning , {}, "warning" );
Info : Tracking and informational purposescaptureMessage ( "Feature flag enabled" , { flag: "new-ui" }, "info" );
Avoid capturing sensitive data
Never log passwords, tokens, or PII without sanitization: // Bad
captureException ( error , {
password: user . password , // Never log passwords!
creditCard: user . card // Never log card numbers!
});
// Good
captureException ( error , {
userId: user . id , // Use IDs instead
hasPaymentMethod: !! user . card // Use boolean flags
});
Don't capture errors in tight loops
Avoid overwhelming your VIJ instance with duplicate errors: // Bad
for ( let i = 0 ; i < 10000 ; i ++ ) {
try {
processItem ( i );
} catch ( error ) {
captureException ( error ); // Will create 10000 errors!
}
}
// Good - batch errors or add deduplication
const errors = [];
for ( let i = 0 ; i < 10000 ; i ++ ) {
try {
processItem ( i );
} catch ( error ) {
errors . push ({ index: i , error });
}
}
if ( errors . length > 0 ) {
captureException ( new Error ( `Batch processing failed` ), {
failedCount: errors . length ,
totalItems: 10000
});
}
Re-throw errors after capturing
Capture the error but don’t swallow it: // Good
try {
await criticalOperation ();
} catch ( error ) {
captureException ( error , { operation: "critical" });
throw error ; // Re-throw for upstream handling
}
// Bad
try {
await criticalOperation ();
} catch ( error ) {
captureException ( error );
// Swallowed! Upstream code won't know about the error
}
Integration Patterns
React Error Boundary
import { Component } from "react" ;
import { captureException } from "vij-sdk" ;
class ErrorBoundary extends Component {
state = { hasError: false };
static getDerivedStateFromError ( error ) {
return { hasError: true };
}
componentDidCatch ( error , errorInfo ) {
captureException ( error , {
componentStack: errorInfo . componentStack ,
route: window . location . pathname
});
}
render () {
if ( this . state . hasError ) {
return < h1 > Something went wrong. </ h1 > ;
}
return this . props . children ;
}
}
Vue Error Handler
import { createApp } from "vue" ;
import { captureException } from "vij-sdk" ;
const app = createApp ( App );
app . config . errorHandler = ( err , instance , info ) => {
captureException ( err , {
componentName: instance ?. $options ?. name ,
errorInfo: info ,
route: window . location . pathname
});
};
app . mount ( "#app" );
Express Error Middleware
import express from "express" ;
import { captureException } from "vij-sdk" ;
const app = express ();
// Routes...
// Error handling middleware (must be last)
app . use (( err , req , res , next ) => {
captureException ( err , {
url: req . originalUrl ,
method: req . method ,
headers: req . headers ,
body: req . body ,
params: req . params ,
query: req . query ,
userId: req . user ?. id
});
res . status ( 500 ). json ({ error: "Internal server error" });
});
Async/Await Error Handling
import { captureException } from "vij-sdk" ;
async function fetchUserData ( userId ) {
try {
const response = await fetch ( `/api/users/ ${ userId } ` );
if ( ! response . ok ) {
throw new Error ( `HTTP ${ response . status } : ${ response . statusText } ` );
}
return await response . json ();
} catch ( error ) {
captureException ( error , {
operation: "fetchUserData" ,
userId ,
timestamp: new Date (). toISOString ()
});
throw error ;
}
}
Troubleshooting
Errors not appearing in dashboard
Check the following :
Verify init() was called before captureException()
Check browser console/server logs for network errors
Ensure VIJ Admin endpoint is accessible
Verify batching settings aren’t delaying delivery too long
Check that error object has name, message, and stack properties
Debug : Disable batching for immediate deliveryinit ({ batch: false , /* ... */ });
Duplicate errors appearing
Cause : Same error being captured multiple timesSolutions :
Check if error is being captured in both automatic handlers and manual try/catch
Implement deduplication logic for recurring errors
Use error grouping features in VIJ Admin dashboard
Learn more about error grouping →
Next Steps