Error Handling
ParticleText.js includes comprehensive error handling to help you identify configuration issues quickly and recover from runtime errors gracefully. Understanding the error system helps you build robust, production-ready applications.
Types of Errors
Section titled “Types of Errors”ParticleText.js handles two types of errors:
- Configuration Errors - Invalid configuration caught during initialization
- Runtime Errors - Unexpected errors during animation execution
Configuration Errors
Section titled “Configuration Errors”These occur immediately when calling initParticleJS() with invalid configuration. The library validates your config and shows a browser alert listing all issues found.
// This will trigger a configuration errorconst instance = initParticleJS('#canvas', {// Missing required 'text' propertycolors: ['#FF0000'],particleRadius: { invalid: { base: 2, rand: 1 } // Invalid breakpoint name}});
// Browser alert appears:// ParticleText.js Configuration Errors:// 1. Missing required 'text' property// 2. Invalid breakpoint 'invalid' in particleRadius...Behavior:
- Browser alert shows all validation errors
- Exception is thrown to stop execution
- Animation does not start
- Console logs the error
Runtime Errors
Section titled “Runtime Errors”These occur during animation execution due to unexpected conditions (browser issues, DOM manipulation, etc.). Runtime errors trigger the onError callback.
const instance = initParticleJS('#canvas', {text: 'SAFE',colors: ['#695aa6'],
onError: function(error) { console.error('Animation error:', error); // Handle error gracefully}});
// If error occurs during animation:// 1. Animation stops automatically// 2. onError callback is called with error object// 3. isAnimating becomes falseBehavior:
- Animation stops automatically (cancelAnimationFrame)
onErrorcallback is called with Error object- Falls back to
console.error()if no callback provided isAnimatingproperty becomesfalse
The onError Callback
Section titled “The onError Callback”The onError configuration option lets you handle runtime errors gracefully instead of breaking your application.
Basic Usage
Section titled “Basic Usage”const instance = initParticleJS('#canvas', {text: 'ERROR DEMO',colors: ['#695aa6'],
onError: function(error) { // error is an Error object with: // - error.message: Error description // - error.stack: Stack trace // - error.name: Error type
console.error('ParticleText error:', error.message);}});Display Error to User
Section titled “Display Error to User”function showErrorMessage(message) {const errorDiv = document.getElementById('error-display');errorDiv.textContent = 'Animation error: ' + message;errorDiv.style.display = 'block';}
const instance = initParticleJS('#canvas', {text: 'USER FRIENDLY',colors: ['#695aa6'],
onError: function(error) { // Log for developers console.error('ParticleText error:', error);
// Show friendly message to users showErrorMessage('Animation temporarily unavailable');}});Error Logging Service
Section titled “Error Logging Service”const instance = initParticleJS('#canvas', {text: 'PRODUCTION',colors: ['#695aa6'],
onError: function(error) { // Log to error tracking service (Sentry, Rollbar, etc.) if (window.Sentry) { Sentry.captureException(error, { tags: { component: 'ParticleText', canvas: '#canvas' }, extra: { isAnimating: instance.isAnimating, particleCount: instance.particleList.length } }); }
// Still log locally console.error('ParticleText error:', error);}});Automatic Retry
Section titled “Automatic Retry”let retryCount = 0;const MAX_RETRIES = 3;
const instance = initParticleJS('#canvas', {text: 'RETRY',colors: ['#695aa6'],
onError: function(error) { console.error('Animation error:', error);
if (retryCount < MAX_RETRIES) { retryCount++; console.log(`Retrying animation (attempt ${retryCount}/${MAX_RETRIES})...`);
// Wait 1 second, then retry setTimeout(() => { instance.startAnimation(); }, 1000); } else { console.error('Max retries reached. Animation stopped.'); alert('Animation could not be started. Please refresh the page.'); }}});Configuration Validation Errors
Section titled “Configuration Validation Errors”ParticleText.js validates all configuration options and provides detailed error messages.
Missing Required Text
Section titled “Missing Required Text”// ❌ Error: Missing required 'text' propertyinitParticleJS('#canvas', {colors: ['#695aa6']});
// ✅ Fix: Provide textinitParticleJS('#canvas', {text: 'HELLO',colors: ['#695aa6']});
// ✅ Alternative: Use data-text attribute// <canvas id="canvas" data-text="HELLO"></canvas>initParticleJS('#canvas', {colors: ['#695aa6']});Invalid Color Format
Section titled “Invalid Color Format”// ❌ Error: Invalid hex color formatinitParticleJS('#canvas', {text: 'COLOR',colors: ['red', '#FFF', 'rgb(255,0,0)'] // Wrong formats});
// ✅ Fix: Use 6-digit hex colorsinitParticleJS('#canvas', {text: 'COLOR',colors: ['#FF0000', '#FFFFFF', '#00FF00'] // Correct format});Invalid Color Weights
Section titled “Invalid Color Weights”// ❌ Error: Weight must be positive integerinitParticleJS('#canvas', {text: 'WEIGHT',colors: [ { color: '#FF0000', weight: 0 }, // Must be > 0 { color: '#00FF00', weight: 2.5 }, // No decimals { color: '#0000FF', weight: -1 } // No negatives]});
// ✅ Fix: Use positive integersinitParticleJS('#canvas', {text: 'WEIGHT',colors: [ { color: '#FF0000', weight: 1 }, { color: '#00FF00', weight: 3 }, { color: '#0000FF', weight: 5 }]});Invalid Breakpoint Names
Section titled “Invalid Breakpoint Names”// ❌ Error: Invalid breakpoint namesinitParticleJS('#canvas', {text: 'BREAKPOINT',colors: ['#695aa6'],particleRadius: { mobile: { base: 2, rand: 1 }, // Not a valid breakpoint desktop: { base: 4, rand: 2 } // Not a valid breakpoint}});
// ✅ Fix: Use valid breakpointsinitParticleJS('#canvas', {text: 'BREAKPOINT',colors: ['#695aa6'],particleRadius: { xs: { base: 2, rand: 1 }, // Valid breakpoint lg: { base: 4, rand: 2 } // Valid breakpoint}});
// Valid breakpoints: xxxs, xxs, xs, sm, md, lg, xl, xxl, xxxlInvalid Particle Radius Structure
Section titled “Invalid Particle Radius Structure”// ❌ Error: Missing base or rand propertiesinitParticleJS('#canvas', {text: 'RADIUS',colors: ['#695aa6'],particleRadius: { xs: { base: 2 } // Missing 'rand'}});
// ✅ Fix: Provide both base and randinitParticleJS('#canvas', {text: 'RADIUS',colors: ['#695aa6'],particleRadius: { xs: { base: 2, rand: 1 } // Both required}});Invalid Friction Structure
Section titled “Invalid Friction Structure”// ❌ Error: Invalid friction formatinitParticleJS('#canvas', {text: 'FRICTION',colors: ['#695aa6'],friction: 0.9 // Must be object or function});
// ✅ Fix: Use object with base and randinitParticleJS('#canvas', {text: 'FRICTION',colors: ['#695aa6'],friction: { base: 0.9, rand: 0.03 }});
// ✅ Alternative: Use functioninitParticleJS('#canvas', {text: 'FRICTION',colors: ['#695aa6'],friction: function() { return { base: 0.9, rand: 0.03 };}});Type Errors
Section titled “Type Errors”// ❌ Error: Wrong typesinitParticleJS('#canvas', {text: 'TYPES',colors: ['#695aa6'],renderTimeThreshold: '100', // Must be number, not stringtrackCursorOnlyInsideCanvas: 'true' // Must be boolean, not string});
// ✅ Fix: Use correct typesinitParticleJS('#canvas', {text: 'TYPES',colors: ['#695aa6'],renderTimeThreshold: 100, // NumbertrackCursorOnlyInsideCanvas: true // Boolean});Common Error Messages Reference
Section titled “Common Error Messages Reference”Configuration Errors
Section titled “Configuration Errors”| Error Message | Cause | Solution |
|---|---|---|
Missing required 'text' property | No text provided | Add text: 'YOUR TEXT' or data-text attribute |
Color at index 0 ('red') is not a valid hex color | Invalid color format | Use 6-digit hex: '#FF0000' |
'colors' array must contain at least one color | Empty colors array | Provide at least one color |
Weight at index 0 must be greater than 0 | Zero or negative weight | Use positive integers only |
Weight at index 0 must be an integer | Decimal weight | Use whole numbers only |
Invalid breakpoint 'mobile' in particleRadius | Wrong breakpoint name | Use: xxxs, xxs, xs, sm, md, lg, xl, xxl, xxxl |
particleRadius.xs must have 'base' and 'rand' properties | Missing properties | Provide both: { base: 2, rand: 1 } |
particleRadius.xs.base and .rand must be numbers | Wrong type | Use numbers, not strings |
'friction' must have 'base' and 'rand' properties | Wrong friction format | Use: { base: 0.9, rand: 0.03 } |
'renderTimeThreshold' must be a number | Wrong type | Use number: 100 not '100' |
'trackCursorOnlyInsideCanvas' must be a boolean | Wrong type | Use: true or false |
Runtime Errors
Section titled “Runtime Errors”Runtime errors are rare but can occur due to:
- Browser compatibility issues
- DOM manipulation during animation
- Memory constraints on slow devices
- Canvas context loss
Error Recovery Patterns
Section titled “Error Recovery Patterns”Graceful Degradation
Section titled “Graceful Degradation”let animationFailed = false;
const instance = initParticleJS('#canvas', {text: 'GRACEFUL',colors: ['#695aa6'],
onError: function(error) { console.error('Animation failed:', error); animationFailed = true;
// Hide canvas, show static fallback document.getElementById('canvas').style.display = 'none'; document.getElementById('fallback-text').style.display = 'block';}});
// HTML:// <canvas id="canvas"></canvas>// <h1 id="fallback-text" style="display:none;">GRACEFUL</h1>User Notification
Section titled “User Notification”const instance = initParticleJS('#canvas', {text: 'NOTIFY',colors: ['#695aa6'],
onError: function(error) { // Log error console.error('ParticleText error:', error);
// Show non-intrusive notification const notification = document.createElement('div'); notification.className = 'error-notification'; notification.textContent = 'Animation unavailable'; notification.style.cssText = 'position: fixed; bottom: 20px; right: 20px; ' + 'background: #f44336; color: white; padding: 12px 20px; ' + 'border-radius: 4px; font-size: 14px; z-index: 1000;';
document.body.appendChild(notification);
// Auto-hide after 5 seconds setTimeout(() => { notification.remove(); }, 5000);}});Feature Detection
Section titled “Feature Detection”// Check for required features before initializingfunction canRunParticleText() {return ( typeof window.requestAnimationFrame !== 'undefined' && typeof document.querySelector !== 'undefined' && !!document.createElement('canvas').getContext);}
if (canRunParticleText()) {const instance = initParticleJS('#canvas', { text: 'FEATURE', colors: ['#695aa6'],
onError: function(error) { console.error('Unexpected error:', error); }});} else {console.warn('ParticleText not supported in this browser');// Show fallback content}Try-Catch Wrapper
Section titled “Try-Catch Wrapper”function safeInitParticleJS(selector, config) {try { const instance = initParticleJS(selector, config);
// Add error handler if not provided if (!config.onError) { instance.onError = function(error) { console.error('ParticleText runtime error:', error); }; }
return instance;} catch (error) { // Configuration error occurred console.error('ParticleText initialization failed:', error.message);
// Extract useful info from error const errors = error.message.split('\n').slice(1); console.table(errors.map(e => ({ Error: e.trim() })));
return null;}}
// Usageconst instance = safeInitParticleJS('#canvas', {text: 'SAFE',colors: ['#695aa6']});
if (instance) {console.log('ParticleText initialized successfully');} else {console.log('ParticleText initialization failed - using fallback');}Best Practices
Section titled “Best Practices”1. Always Provide onError in Production
Section titled “1. Always Provide onError in Production”// ✅ Good: Handle errors gracefullyconst instance = initParticleJS('#canvas', {text: 'PRODUCTION',colors: ['#695aa6'],
onError: function(error) { console.error('Animation error:', error); // Handle gracefully}});
// ❌ Bad: No error handlingconst instance = initParticleJS('#canvas', {text: 'PRODUCTION',colors: ['#695aa6']// Errors only go to console});2. Log Errors to Monitoring Service
Section titled “2. Log Errors to Monitoring Service”// ✅ Good: Track errors in productionconst instance = initParticleJS('#canvas', {text: 'MONITORED',colors: ['#695aa6'],
onError: function(error) { // Send to error tracking if (typeof Sentry !== 'undefined') { Sentry.captureException(error); }
// Also log locally console.error('ParticleText error:', error);}});3. Validate Config During Development
Section titled “3. Validate Config During Development”// ✅ Good: Validate early in developmentconst config = {text: 'VALIDATE',colors: ['#695aa6'],particleRadius: { xs: { base: 2, rand: 1 }, lg: { base: 4, rand: 2 }}};
// Development-only validationif (process.env.NODE_ENV === 'development') {console.log('Initializing ParticleText with config:', config);}
const instance = initParticleJS('#canvas', config);4. Provide User Feedback
Section titled “4. Provide User Feedback”// ✅ Good: Let users know what happenedconst instance = initParticleJS('#canvas', {text: 'FEEDBACK',colors: ['#695aa6'],
onError: function(error) { console.error('Animation error:', error);
// Show user-friendly message document.getElementById('error-message').textContent = 'Animation temporarily unavailable. Page functionality is not affected.';}});
// ❌ Bad: Silent failureconst instance = initParticleJS('#canvas', {text: 'SILENT',colors: ['#695aa6'],
onError: function(error) { // User has no idea anything went wrong}});5. Clean Up on Error
Section titled “5. Clean Up on Error”// ✅ Good: Clean up resourcesconst instance = initParticleJS('#canvas', {text: 'CLEANUP',colors: ['#695aa6'],
onError: function(error) { console.error('Animation error:', error);
// Clean up instance.destroy();
// Clear canvas const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height);
// Remove from DOM if needed // canvas.remove();}});Debugging Errors
Section titled “Debugging Errors”Enable Verbose Logging
Section titled “Enable Verbose Logging”const DEBUG = true;
const instance = initParticleJS('#canvas', {text: 'DEBUG',colors: ['#695aa6'],
onError: function(error) { if (DEBUG) { console.group('ParticleText Error Details'); console.error('Error:', error); console.log('Error message:', error.message); console.log('Stack trace:', error.stack); console.log('Animation state:', { isAnimating: instance.isAnimating, particleCount: instance.particleList.length, currentBreakpoint: instance.getCurrentBreakpoint() }); console.groupEnd(); } else { console.error('Animation error:', error.message); }}});Catch Configuration Errors
Section titled “Catch Configuration Errors”function debugInitParticleJS(selector, config) {console.log('Attempting to initialize ParticleText...');console.log('Selector:', selector);console.log('Config:', config);
try { const instance = initParticleJS(selector, config); console.log('✓ ParticleText initialized successfully'); return instance;} catch (error) { console.error('✗ ParticleText initialization failed'); console.error('Error:', error.message);
// Parse error message to show each issue if (error.message.includes('Configuration Errors:')) { const errorLines = error.message.split('\n'); console.group('Configuration Issues:'); errorLines.slice(1).forEach(line => { if (line.trim()) console.error(line.trim()); }); console.groupEnd(); }
return null;}}
// Usageconst instance = debugInitParticleJS('#canvas', {text: 'DEBUG',colors: ['invalid-color'] // Will trigger error});Monitor Animation State
Section titled “Monitor Animation State”const instance = initParticleJS('#canvas', {text: 'MONITOR',colors: ['#695aa6'],
onError: function(error) { console.error('Error occurred:', error);}});
// Monitor state periodicallysetInterval(() => {console.log('Animation Status:', { isAnimating: instance.isAnimating, particleCount: instance.particleList.length, breakpoint: instance.getCurrentBreakpoint()});}, 5000);
// Monitor for animation stopslet wasAnimating = instance.isAnimating;setInterval(() => {if (wasAnimating && !instance.isAnimating) { console.warn('Animation stopped unexpectedly!');}wasAnimating = instance.isAnimating;}, 1000);Framework Integration
Section titled “Framework Integration”React Error Boundary
Section titled “React Error Boundary”import { Component } from 'react';
class ParticleTextErrorBoundary extends Component {constructor(props) { super(props); this.state = { hasError: false, error: null };}
static getDerivedStateFromError(error) { return { hasError: true, error };}
componentDidCatch(error, errorInfo) { console.error('ParticleText error:', error, errorInfo);}
render() { if (this.state.hasError) { return ( <div className="error-fallback"> <h2>Animation Unavailable</h2> <p>The particle animation could not be loaded.</p> </div> ); }
return this.props.children;}}
// Usagefunction App() {return ( <ParticleTextErrorBoundary> <ParticleTextComponent /> </ParticleTextErrorBoundary>);}React Hook with Error State
Section titled “React Hook with Error State”import { useEffect, useState } from 'react';
function useParticleText(selector, config) {const [error, setError] = useState(null);const [instance, setInstance] = useState(null);
useEffect(() => { try { const particleInstance = initParticleJS(selector, { ...config, onError: (err) => { setError(err); if (config.onError) { config.onError(err); } } });
setInstance(particleInstance);
return () => { particleInstance.destroy(); }; } catch (err) { setError(err); }}, [selector, config]);
return { instance, error };}
// Usagefunction ParticleTextComponent() {const { instance, error } = useParticleText('#canvas', { text: 'REACT', colors: ['#61DAFB']});
if (error) { return <div className="error">Animation failed: {error.message}</div>;}
return <canvas id="canvas" width="1800" height="400" />;}Vue Error Handling
Section titled “Vue Error Handling”export default {name: 'ParticleText',
data() { return { instance: null, error: null };},
mounted() { try { this.instance = initParticleJS('#canvas', { text: 'VUE', colors: ['#42B883'],
onError: (error) => { this.error = error; console.error('ParticleText error:', error); } }); } catch (error) { this.error = error; console.error('ParticleText initialization failed:', error); }},
beforeUnmount() { if (this.instance) { this.instance.destroy(); }},
errorCaptured(err, instance, info) { console.error('Vue error boundary caught:', err, info); return false; // Propagate error}};Production Error Handling
Section titled “Production Error Handling”Complete Production Setup
Section titled “Complete Production Setup”// Production-ready error handlingconst IS_PRODUCTION = process.env.NODE_ENV === 'production';
function initParticleTextSafely(selector, config) {// Feature detectionif (!window.requestAnimationFrame || !document.createElement('canvas').getContext) { console.warn('ParticleText not supported'); return null;}
// Add production error handlerconst productionConfig = { ...config, onError: function(error) { // Log to monitoring service if (IS_PRODUCTION && window.Sentry) { Sentry.captureException(error, { tags: { component: 'ParticleText' }, extra: { selector, configKeys: Object.keys(config) } }); }
// Log locally console.error('ParticleText error:', error);
// Show user feedback const errorDiv = document.getElementById('animation-error'); if (errorDiv) { errorDiv.textContent = 'Animation temporarily unavailable'; errorDiv.style.display = 'block'; }
// Call custom error handler if (config.onError) { config.onError(error); } }};
try { return initParticleJS(selector, productionConfig);} catch (error) { // Configuration error if (IS_PRODUCTION && window.Sentry) { Sentry.captureException(error, { tags: { component: 'ParticleText', phase: 'initialization' } }); }
console.error('ParticleText init failed:', error.message); return null;}}
// Usageconst instance = initParticleTextSafely('#canvas', {text: 'PRODUCTION',colors: ['#695aa6']});
if (!instance) {// Show fallbackdocument.getElementById('fallback-content').style.display = 'block';}Testing Error Scenarios
Section titled “Testing Error Scenarios”Simulate Configuration Errors
Section titled “Simulate Configuration Errors”// Test invalid configurations during developmentconst testConfigs = [{ name: 'Missing text', config: { colors: ['#695aa6'] } },{ name: 'Invalid color', config: { text: 'TEST', colors: ['red'] } },{ name: 'Invalid weight', config: { text: 'TEST', colors: [{ color: '#FF0000', weight: -1 }] } },{ name: 'Invalid breakpoint', config: { text: 'TEST', particleRadius: { mobile: { base: 2, rand: 1 } } } }];
testConfigs.forEach(({ name, config }) => {console.log(`Testing: ${name}`);try { initParticleJS('#test-canvas', config); console.log('✗ Expected error but succeeded');} catch (error) { console.log('✓ Correctly caught error:', error.message.split('\n')[0]);}});Troubleshooting
Section titled “Troubleshooting”Animation stops without calling onError?
- Check browser console for errors
- Verify canvas element exists and is visible
- Check if destroy() was called elsewhere
onError not being called?
- Ensure you’re testing runtime errors, not configuration errors
- Configuration errors throw before onError can be registered
- Check that animation actually started
Multiple error alerts appearing?
- Each call to
initParticleJS()validates independently - Store instance and reuse instead of reinitializing
- Check for duplicate initialization code
Error messages unclear?
- Enable verbose logging in development
- Check browser console for full stack trace
- Review configuration against API documentation
Can’t recover from error?
- Call
destroy()before attempting restart - Check that canvas element is still in DOM
- Verify no memory leaks from previous instances
Related Documentation
Section titled “Related Documentation”- Configuration Reference - All configuration options
- Methods Reference - Available methods including destroy()
- Manual Control - Controlling animation lifecycle
- Performance Optimization - Prevent performance-related errors