0
# Error Classes
1
2
VError provides three additional specialized error classes beyond the main VError class: SError for strict printf interpretation, WError for wrapped error messages, and MultiError for handling multiple errors from parallel operations.
3
4
## Capabilities
5
6
### SError Class
7
8
SError is identical to VError but enforces strict interpretation of printf-style arguments, throwing errors when null or undefined values are passed to printf specifiers instead of converting them to strings.
9
10
```javascript { .api }
11
/**
12
* SError constructor - same signatures as VError with strict printf parsing
13
* @param {Error|Object|string} [causeOrOptionsOrMessage] - Cause error, options object, or message
14
* @param {...*} args - Printf-style arguments (strict interpretation)
15
*/
16
function SError(causeOrOptionsOrMessage, ...args);
17
18
// Inherits all VError properties and methods
19
// Name defaults to 'VError' (not 'SError') after construction
20
```
21
22
**Usage Examples:**
23
24
```javascript
25
const VError = require('verror');
26
const SError = VError.SError;
27
28
// Valid usage
29
const err1 = new SError('user %s not found', 'john');
30
31
// This will throw an error (strict mode)
32
try {
33
const err2 = new SError('value is %s', null); // Throws error
34
} catch (e) {
35
console.log('SError rejected null value');
36
}
37
38
// Compare with VError (non-strict)
39
const VError = require('verror');
40
const err3 = new VError('value is %s', null); // Works, becomes "value is null"
41
```
42
43
### WError Class
44
45
WError wraps errors while hiding lower-level error messages from the top-level error. The cause message is not appended to the main message, but the cause chain is preserved for debugging and the cause information appears in toString() output.
46
47
```javascript { .api }
48
/**
49
* WError constructor that hides cause messages from main message
50
* @param {Error|Object|string} [causeOrOptionsOrMessage] - Cause error, options object, or message
51
* @param {...*} args - Printf-style arguments for message formatting
52
*/
53
function WError(causeOrOptionsOrMessage, ...args);
54
55
interface WErrorInstance extends VErrorInstance {
56
/** WError name */
57
name: 'WError';
58
}
59
```
60
61
#### WError Instance Methods
62
63
```javascript { .api }
64
/**
65
* Custom toString that shows cause in "caused by" format
66
* @returns {string} Error string with cause information
67
*/
68
toString(): string;
69
70
/**
71
* Get or set the cause (historical compatibility method)
72
* @param {Error} [newCause] - Optional new cause to set
73
* @returns {Error} Current cause error
74
*/
75
cause(newCause?: Error): Error;
76
```
77
78
**Usage Examples:**
79
80
```javascript
81
const VError = require('verror');
82
const WError = VError.WError;
83
84
const originalError = new Error('database connection failed');
85
const wrappedError = new WError(originalError, 'user operation failed');
86
87
// Message only shows the wrapper message
88
console.log(wrappedError.message); // "user operation failed"
89
90
// But toString shows both
91
console.log(wrappedError.toString()); // "WError: user operation failed; caused by Error: database connection failed"
92
93
// Cause is still accessible
94
console.log(VError.cause(wrappedError) === originalError); // true
95
96
// Historical cause() method can get/set
97
console.log(wrappedError.cause() === originalError); // true
98
const newCause = new Error('different error');
99
wrappedError.cause(newCause);
100
console.log(wrappedError.cause() === newCause); // true
101
```
102
103
### MultiError Class
104
105
MultiError represents a collection of errors for consumers that generally only deal with one error. It encapsulates multiple errors but can be treated as a single error with a summary message.
106
107
```javascript { .api }
108
/**
109
* MultiError constructor for handling multiple errors
110
* @param {Error[]} errors - Array of Error objects (at least 1 required)
111
*/
112
function MultiError(errors);
113
114
interface MultiErrorInstance extends VErrorInstance {
115
/** MultiError name */
116
name: 'MultiError';
117
118
/** Internal errors array */
119
ase_errors: Error[];
120
}
121
```
122
123
#### MultiError Instance Methods
124
125
```javascript { .api }
126
/**
127
* Returns a copy of the errors array
128
* @returns {Error[]} Copy of all contained errors
129
*/
130
errors(): Error[];
131
```
132
133
**Usage Examples:**
134
135
```javascript
136
const VError = require('verror');
137
const MultiError = VError.MultiError;
138
139
// Create from multiple errors
140
const errors = [
141
new Error('validation failed for field "email"'),
142
new Error('validation failed for field "age"'),
143
new Error('validation failed for field "name"')
144
];
145
146
const multiError = new MultiError(errors);
147
148
console.log(multiError.message); // "first of 3 errors"
149
console.log(multiError.name); // "MultiError"
150
151
// Access individual errors
152
const individualErrors = multiError.errors();
153
console.log(individualErrors.length); // 3
154
console.log(individualErrors[0].message); // "validation failed for field "email""
155
156
// The first error becomes the cause
157
const VError = require('verror');
158
console.log(VError.cause(multiError) === errors[0]); // true
159
160
// Use with errorForEach utility
161
VError.errorForEach(multiError, function(err) {
162
console.log('Error:', err.message);
163
});
164
// Prints each individual error message
165
```
166
167
### Error Class Comparison
168
169
Summary of differences between the error classes:
170
171
```javascript { .api }
172
/**
173
* Class behavior comparison:
174
*
175
* VError:
176
* - Default behavior, cause message appended to main message
177
* - Non-strict printf (null/undefined converted to strings)
178
* - Name: 'VError'
179
*
180
* SError:
181
* - Strict printf (null/undefined cause errors)
182
* - Otherwise identical to VError
183
* - Name: 'VError' (inherits from VError)
184
*
185
* WError:
186
* - Cause message NOT appended to main message
187
* - toString() shows cause in "caused by" format
188
* - Historical cause() method can set cause
189
* - Name: 'WError'
190
*
191
* MultiError:
192
* - Contains multiple errors
193
* - Summary message: "first of N error(s)"
194
* - First error becomes the cause
195
* - Name: 'MultiError'
196
*/
197
```
198
199
**Usage Examples:**
200
201
```javascript
202
const VError = require('verror');
203
const { SError, WError, MultiError } = VError;
204
205
const originalError = new Error('underlying issue');
206
207
// VError: cause message included
208
const vErr = new VError(originalError, 'operation failed');
209
console.log(vErr.message); // "operation failed: underlying issue"
210
211
// WError: cause message hidden
212
const wErr = new WError(originalError, 'operation failed');
213
console.log(wErr.message); // "operation failed"
214
console.log(wErr.toString()); // "WError: operation failed; caused by Error: underlying issue"
215
216
// SError: strict printf
217
const sErr = new SError('valid message with %s', 'string'); // OK
218
// const sErr2 = new SError('invalid %s', null); // Would throw
219
220
// MultiError: multiple errors
221
const multi = new MultiError([
222
new Error('error 1'),
223
new Error('error 2')
224
]);
225
console.log(multi.message); // "first of 2 errors"
226
```
227
228
### Common Patterns
229
230
Typical usage patterns for different error classes:
231
232
```javascript { .api }
233
/**
234
* Common usage patterns:
235
*
236
* VError: General error chaining, preserving all context
237
* SError: When you want strict validation of printf arguments
238
* WError: API endpoints where internal errors should be hidden
239
* MultiError: Parallel operations that may generate multiple errors
240
*/
241
```
242
243
**Usage Examples:**
244
245
```javascript
246
// VError: Server-side error chaining
247
function readConfigFile(filename) {
248
return fs.readFile(filename).catch(err => {
249
throw new VError(err, 'failed to read config file "%s"', filename);
250
});
251
}
252
253
// WError: API error wrapping (hide internal details)
254
app.get('/api/users', async (req, res) => {
255
try {
256
const users = await getUsersFromDatabase();
257
res.json(users);
258
} catch (dbError) {
259
const apiError = new WError(dbError, 'failed to retrieve users');
260
res.status(500).json({ error: apiError.message }); // Only shows "failed to retrieve users"
261
logger.error(apiError.toString()); // Logs full cause chain
262
}
263
});
264
265
// MultiError: Parallel validation
266
async function validateUserData(userData) {
267
const validationPromises = [
268
validateEmail(userData.email),
269
validateAge(userData.age),
270
validateName(userData.name)
271
];
272
273
const results = await Promise.allSettled(validationPromises);
274
const errors = results
275
.filter(result => result.status === 'rejected')
276
.map(result => result.reason);
277
278
if (errors.length > 0) {
279
throw new MultiError(errors);
280
}
281
}
282
```