AggregateError: Handling Multiple Errors in JavaScript

Learn to use AggregateError for cleaner, more informative error handling in async JavaScript applications. Master the ES2021 feature that wraps multiple errors in a single object.

What is AggregateError?

Managing multiple concurrent operations that can fail in different ways is a common challenge in modern web development. AggregateError provides an elegant solution by wrapping multiple errors in a single error object, allowing you to handle several failures at once rather than dealing with them one at a time.

Introduced in ES2021 (ECMAScript 2021), AggregateError is a built-in JavaScript object that represents several errors needing to be reported by an operation. It extends the base Error class, so it inherits all Error properties and methods while adding the ability to contain multiple individual errors.

Why AggregateError Matters

Before AggregateError, developers had to create custom error objects or use workarounds to collect and report multiple failures. With modern applications making numerous concurrent API calls and processing batch operations, having a standard way to represent multiple errors has become essential for robust error handling in JavaScript applications. When working with AI-powered automation workflows that process multiple data streams, AggregateError helps you capture and respond to all failures systematically.

Constructor and Syntax

The AggregateError constructor follows a straightforward pattern that accepts an iterable of errors and optional message and configuration parameters.

Constructor Parameters

ParameterTypeRequiredDescription
errorsIterableYesAn iterable of errors - can be Error instances or any values
messagestringNoHuman-readable description of what went wrong
optionsobjectNoConfiguration object with cause property

Basic Syntax

// Basic usage
new AggregateError(errors)

// With message
new AggregateError(errors, "Operation failed with multiple errors")

// With cause for error chaining
new AggregateError(errors, "Batch processing failed", { cause: originalError })

The constructor can be called with or without the new keyword - both approaches create a valid AggregateError instance.

Working with AggregateError Instances

When you catch an AggregateError, you have access to all standard Error properties plus the additional errors array that contains the aggregated failures.

Instance Properties

PropertyTypeDescription
errorsError[]Array containing all the aggregated errors
messagestringThe error message (inherited from Error)
namestringAlways "AggregateError" (inherited from Error)
causeunknownThe underlying cause if provided (inherited from Error)

Accessing Individual Errors

try {
 // code that throws AggregateError
} catch (error) {
 if (error instanceof AggregateError) {
 console.log(`Total failures: ${error.errors.length}`);
 
 error.errors.forEach((err, index) => {
 console.log(`Error ${index + 1}:`, err.message);
 });
 }
}

The errors array maintains the original order of the errors as they were provided to the constructor, allowing you to trace back each failure to its source operation.

Practical Use Cases

Promise.any() Integration

The most common built-in use of AggregateError is with Promise.any(). When all promises passed to Promise.any() reject, it throws an AggregateError containing all the rejection reasons:

const endpoints = [
 fetch('/api/data1'),
 fetch('/api/data2'),
 fetch('/api/data3')
];

try {
 const result = await Promise.any(endpoints);
 console.log('First successful response:', result);
} catch (error) {
 if (error instanceof AggregateError) {
 console.log(`${error.errors.length} requests failed`);
 error.errors.forEach(err => console.error(err.message));
 
 // Display user-friendly summary
 showUserFeedback(`${error.errors.length} endpoints are currently unavailable`);
 }
}

Batch Processing Validation

When processing a batch of items where each operation can fail independently, AggregateError lets you collect all failures and report them comprehensively:

async function processBatch(items) {
 const errors = [];

 for (const item of items) {
 try {
 await processItem(item);
 } catch (error) {
 errors.push(new Error(`Item ${item.id}: ${error.message}`));
 }
 }

 if (errors.length > 0) {
 throw new AggregateError(
 errors, 
 `Failed to process ${errors.length} items out of ${items.length}`
 );
 }
}

Form Validation

AggregateError excels at collecting multiple validation errors before presenting them to users:

function validateForm(formData) {
 const errors = [];

 if (!formData.email || !formData.email.includes('@')) {
 errors.push(new Error('Please enter a valid email address'));
 }
 
 if (!formData.password || formData.password.length < 8) {
 errors.push(new Error('Password must be at least 8 characters'));
 }
 
 if (formData.password !== formData.confirmPassword) {
 errors.push(new Error('Passwords do not match'));
 }

 if (errors.length > 0) {
 throw new AggregateError(errors, 'Please fix the following issues');
 }
}

Browser Support and Compatibility

AggregateError is part of the Baseline "widely available" set of features, meaning it works across all modern browsers:

BrowserVersionRelease Date
Chrome85+September 2020
Firefox79+July 2020
Safari14+September 2020
Edge85+September 2020

Polyfills for Legacy Environments

For applications that need to support older browsers, polyfills are available:

  • core-js: The comprehensive polyfill library includes AggregateError support
  • es-aggregate-error: A focused polyfill package for just AggregateError
// Using core-js
import 'core-js/stable/aggregate-error';

// Using the focused polyfill
import AggregateError from 'es-aggregate-error';

When using polyfills, ensure they load before any code that uses AggregateError to prevent runtime errors.

Best Practices

When to Use AggregateError

  • Multiple independent operations that can fail separately
  • Collecting all failures before making decisions on how to proceed
  • Providing comprehensive error information to users or logging systems

When NOT to Use AggregateError

  • Causally related errors - use error chaining with the cause property instead
  • Single error scenarios - use a regular Error object
  • Performance-critical paths with potentially large error sets

Error Message Design

Craft clear, actionable error messages that summarize the aggregate while providing actionable guidance:

// Good: Specific and informative
throw new AggregateError(
 errors, 
 `Failed to import ${errors.length} records. Please review the errors below.`
);

// Avoid: Vague messages
throw new AggregateError(errors, 'Error');

Limiting Error Counts

For operations that could potentially generate hundreds of errors, consider capping the collection to prevent memory issues:

const MAX_ERRORS = 100;
const errors = collectedErrors.slice(0, MAX_ERRORS);

if (collectedErrors.length > MAX_ERRORS) {
 errors.push(new Error(
 `... and ${collectedErrors.length - MAX_ERRORS} more errors (not shown)`
 ));
}

throw new AggregateError(
 errors, 
 `Processing failed with ${collectedErrors.length} total errors`
);

Error Handling Patterns

Comprehensive Catching

Handle AggregateError alongside regular errors in a production-ready pattern:

async function robustOperation() {
 try {
 await riskyOperation();
 } catch (error) {
 if (error instanceof AggregateError) {
 // Handle multiple errors with context
 logAggregateError(error);
 displayMultipleErrors(error.errors);
 } else if (error instanceof Error) {
 // Handle single error
 logError(error);
 displaySingleError(error);
 }
 }
}

User-Friendly Error Presentation

Transform technical AggregateError instances into user-friendly feedback:

function presentErrors(error) {
 if (error instanceof AggregateError) {
 const messages = error.errors.map(err => err.message);
 return {
 title: 'Multiple Issues Found',
 message: `Please fix the following ${messages.length} issues:`,
 details: messages.map(m => `- ${m}`).join('\n')
 };
 }
 return {
 title: 'An Error Occurred',
 message: error.message
 };
}

Related JavaScript Features

  • Promise.allSettled(): Returns an array of result objects for each promise, avoiding AggregateError but requiring manual iteration
  • Error cause chain: Use the cause property when you need to preserve the original error chain
  • Custom error types: Extend Error or AggregateError for domain-specific error hierarchies

For more on building robust JavaScript applications with proper error handling, explore our web development services.

Frequently Asked Questions

Build Robust Error Handling in Your Web Applications

Our team specializes in modern JavaScript development with best practices for error handling, async operations, and performance optimization.

Sources

  1. MDN Web Docs - AggregateError - Comprehensive documentation on AggregateError syntax, properties, and usage
  2. MDN Web Docs - AggregateError() constructor - Constructor parameters and usage patterns
  3. TC39 ECMAScript Specification - Official language specification defining AggregateError behavior