0
# Error Handling
1
2
Comprehensive error classes and handling mechanisms for validation, configuration, and data format issues. The sitemap library provides detailed error reporting to help identify and resolve issues with sitemap data.
3
4
## Capabilities
5
6
### Error Levels and Handlers
7
8
Control how validation errors are handled throughout the library.
9
10
```typescript { .api }
11
/**
12
* How to handle errors in passed in urls
13
*/
14
enum ErrorLevel {
15
/** Validation will be skipped and nothing logged or thrown */
16
SILENT = 'silent',
17
/** If an invalid value is encountered, a console.warn will be called with details */
18
WARN = 'warn',
19
/** An Error will be thrown on encountering invalid data */
20
THROW = 'throw'
21
}
22
23
/**
24
* Custom error handler function type
25
* @param error - The validation error that occurred
26
* @param level - Error level that triggered the handler
27
*/
28
type ErrorHandler = (error: Error, level: ErrorLevel) => void;
29
```
30
31
### Configuration and URL Errors
32
33
Errors related to missing or invalid configuration and URL data.
34
35
```typescript { .api }
36
/**
37
* Thrown when a sitemap item is missing a required URL
38
*/
39
class NoURLError extends Error {
40
constructor(message?: string);
41
}
42
43
/**
44
* Thrown when required configuration is missing
45
*/
46
class NoConfigError extends Error {
47
constructor(message?: string);
48
}
49
50
/**
51
* Thrown when target folder is not specified for file operations
52
*/
53
class UndefinedTargetFolder extends Error {
54
constructor(message?: string);
55
}
56
```
57
58
### Sitemap Data Validation Errors
59
60
Errors for invalid sitemap item properties and values.
61
62
```typescript { .api }
63
/**
64
* Thrown when change frequency value is invalid
65
*/
66
class ChangeFreqInvalidError extends Error {
67
constructor(message?: string);
68
}
69
70
/**
71
* Thrown when priority value is not between 0.0 and 1.0
72
*/
73
class PriorityInvalidError extends Error {
74
constructor(message?: string);
75
}
76
77
/**
78
* Thrown when an attribute has an invalid value
79
*/
80
class InvalidAttrValue extends Error {
81
constructor(message?: string);
82
}
83
84
/**
85
* Internal error for malformed attributes
86
*/
87
class InvalidAttr extends Error {
88
constructor(message?: string);
89
}
90
```
91
92
### Video Sitemap Errors
93
94
Specialized errors for video sitemap validation.
95
96
```typescript { .api }
97
/**
98
* Thrown when video format is invalid
99
*/
100
class InvalidVideoFormat extends Error {
101
constructor(message?: string);
102
}
103
104
/**
105
* Thrown when video duration is invalid or missing
106
*/
107
class InvalidVideoDuration extends Error {
108
constructor(message?: string);
109
}
110
111
/**
112
* Thrown when video description exceeds 2048 characters
113
*/
114
class InvalidVideoDescription extends Error {
115
constructor(message?: string);
116
}
117
118
/**
119
* Thrown when video title exceeds maximum length
120
*/
121
class InvalidVideoTitle extends Error {
122
constructor(message?: string);
123
}
124
125
/**
126
* Thrown when video rating is not between 0.0 and 5.0
127
*/
128
class InvalidVideoRating extends Error {
129
constructor(message?: string);
130
}
131
132
/**
133
* Thrown when video view count is invalid
134
*/
135
class InvalidVideoViewCount extends Error {
136
constructor(message?: string);
137
}
138
139
/**
140
* Thrown when more than 32 video tags are provided
141
*/
142
class InvalidVideoTagCount extends Error {
143
constructor(message?: string);
144
}
145
146
/**
147
* Thrown when video category exceeds 256 characters
148
*/
149
class InvalidVideoCategory extends Error {
150
constructor(message?: string);
151
}
152
153
/**
154
* Thrown when family_friendly value is invalid
155
*/
156
class InvalidVideoFamilyFriendly extends Error {
157
constructor(message?: string);
158
}
159
160
/**
161
* Thrown when video restriction format is invalid
162
*/
163
class InvalidVideoRestriction extends Error {
164
constructor(message?: string);
165
}
166
167
/**
168
* Thrown when restriction relationship is not allow/deny
169
*/
170
class InvalidVideoRestrictionRelationship extends Error {
171
constructor(message?: string);
172
}
173
174
/**
175
* Thrown when video price type is invalid
176
*/
177
class InvalidVideoPriceType extends Error {
178
constructor(message?: string);
179
}
180
181
/**
182
* Thrown when video resolution is invalid
183
*/
184
class InvalidVideoResolution extends Error {
185
constructor(message?: string);
186
}
187
188
/**
189
* Thrown when video price currency is not ISO 4217 format
190
*/
191
class InvalidVideoPriceCurrency extends Error {
192
constructor(message?: string);
193
}
194
```
195
196
### News Sitemap Errors
197
198
Errors specific to news sitemap validation.
199
200
```typescript { .api }
201
/**
202
* Thrown when news format is invalid
203
*/
204
class InvalidNewsFormat extends Error {
205
constructor(message?: string);
206
}
207
208
/**
209
* Thrown when news access value is not Registration or Subscription
210
*/
211
class InvalidNewsAccessValue extends Error {
212
constructor(message?: string);
213
}
214
```
215
216
### Stream and XML Errors
217
218
Errors related to stream processing and XML validation.
219
220
```typescript { .api }
221
/**
222
* Thrown when a stream is empty when data is expected
223
*/
224
class EmptyStream extends Error {
225
constructor(message?: string);
226
}
227
228
/**
229
* Thrown when a sitemap is empty when data is expected
230
*/
231
class EmptySitemap extends Error {
232
constructor(message?: string);
233
}
234
235
/**
236
* Thrown when XMLLint is not available for validation
237
*/
238
class XMLLintUnavailable extends Error {
239
constructor(message?: string);
240
}
241
```
242
243
## Usage Examples
244
245
### Custom Error Handling
246
247
```typescript
248
import {
249
validateSMIOptions,
250
ErrorLevel,
251
ErrorHandler,
252
PriorityInvalidError
253
} from "sitemap";
254
255
// Collect validation errors instead of throwing
256
const validationErrors: Error[] = [];
257
258
const errorCollector: ErrorHandler = (error, level) => {
259
validationErrors.push(error);
260
console.warn(`Validation ${level}: ${error.message}`);
261
262
// Only throw on critical errors
263
if (level === ErrorLevel.THROW) {
264
throw error;
265
}
266
};
267
268
// Validate sitemap items with custom error handling
269
const items = [
270
{ url: '/page1', priority: 1.5 }, // Invalid priority > 1.0
271
{ url: '/page2', changefreq: 'sometimes' }, // Invalid changefreq
272
{ url: '/page3' } // Valid item
273
];
274
275
const validatedItems = items.map(item => {
276
try {
277
return validateSMIOptions(item, ErrorLevel.WARN, errorCollector);
278
} catch (error) {
279
console.error('Critical validation error:', error.message);
280
return null;
281
}
282
}).filter(Boolean);
283
284
console.log(`Processed ${items.length} items, ${validatedItems.length} valid, ${validationErrors.length} errors`);
285
```
286
287
### Error Type Checking
288
289
```typescript
290
import {
291
InvalidVideoFormat,
292
InvalidVideoDuration,
293
PriorityInvalidError
294
} from "sitemap";
295
296
function handleSitemapError(error: Error) {
297
if (error instanceof PriorityInvalidError) {
298
console.log('Priority must be between 0.0 and 1.0');
299
// Handle priority errors
300
} else if (error instanceof InvalidVideoFormat) {
301
console.log('Video format is not supported');
302
// Handle video format errors
303
} else if (error instanceof InvalidVideoDuration) {
304
console.log('Video duration must be a positive number');
305
// Handle video duration errors
306
} else {
307
console.log('Unknown validation error:', error.message);
308
// Handle other errors
309
}
310
}
311
312
// Usage in validation pipeline
313
try {
314
const validatedItem = validateSMIOptions(sitemapItem, ErrorLevel.THROW);
315
processSitemapItem(validatedItem);
316
} catch (error) {
317
handleSitemapError(error as Error);
318
}
319
```
320
321
### Batch Processing with Error Recovery
322
323
```typescript
324
import {
325
normalizeURL,
326
validateSMIOptions,
327
ErrorLevel,
328
NoURLError,
329
ChangeFreqInvalidError
330
} from "sitemap";
331
332
interface ProcessingResult {
333
successful: SitemapItem[];
334
failed: Array<{ item: any; error: Error }>;
335
}
336
337
function processSitemapBatch(rawItems: any[], hostname: string): ProcessingResult {
338
const successful: SitemapItem[] = [];
339
const failed: Array<{ item: any; error: Error }> = [];
340
341
for (const rawItem of rawItems) {
342
try {
343
// First normalize the URL
344
const normalized = normalizeURL(rawItem, hostname);
345
346
// Then validate the complete item
347
const validated = validateSMIOptions(normalized, ErrorLevel.THROW);
348
349
successful.push(validated);
350
} catch (error) {
351
const err = error as Error;
352
353
// Log specific error types differently
354
if (err instanceof NoURLError) {
355
console.warn('Skipping item without URL:', rawItem);
356
} else if (err instanceof ChangeFreqInvalidError) {
357
console.warn('Invalid changefreq, using default:', rawItem);
358
// Could attempt to fix and retry
359
} else {
360
console.error('Validation failed for item:', rawItem, err.message);
361
}
362
363
failed.push({ item: rawItem, error: err });
364
}
365
}
366
367
return { successful, failed };
368
}
369
370
// Usage
371
const rawData = [
372
{ url: '/page1', changefreq: 'invalid' },
373
{ url: '/page2', priority: 'high' }, // Should be number
374
{ changefreq: 'daily' }, // Missing URL
375
{ url: '/page3', priority: 0.8 } // Valid
376
];
377
378
const result = processSitemapBatch(rawData, 'https://example.com');
379
console.log(`${result.successful.length} valid, ${result.failed.length} failed`);
380
```
381
382
### Stream Error Handling
383
384
```typescript
385
import {
386
SitemapStream,
387
ErrorLevel,
388
EmptyStream,
389
InvalidAttrValue
390
} from "sitemap";
391
392
const sitemap = new SitemapStream({
393
hostname: 'https://example.com',
394
level: ErrorLevel.WARN,
395
errorHandler: (error, level) => {
396
if (error instanceof InvalidAttrValue) {
397
console.warn('Invalid attribute value, skipping:', error.message);
398
return; // Continue processing
399
} else if (error instanceof EmptyStream) {
400
console.error('Stream is empty, no sitemap generated');
401
throw error; // Stop processing
402
} else {
403
console.log(`${level} error:`, error.message);
404
}
405
}
406
});
407
408
sitemap.on('error', (error) => {
409
console.error('Stream error:', error.message);
410
// Handle stream-level errors
411
});
412
413
// Write items with potential validation issues
414
sitemap.write({ url: '/page1', priority: 'invalid' }); // Will trigger error handler
415
sitemap.write({ url: '/page2' }); // Valid item
416
sitemap.end();
417
```