0
# Error Handling
1
2
Comprehensive error reporting system with position information, warning messages, and configurable logging. The YAML library provides detailed error tracking for robust YAML processing and debugging capabilities.
3
4
## Capabilities
5
6
### Error Classes
7
8
The library provides three main error classes for different types of issues encountered during YAML processing.
9
10
```typescript { .api }
11
/**
12
* Base error class for all YAML-related errors
13
*/
14
class YAMLError extends Error {
15
/** Error name identifier */
16
name: 'YAMLError';
17
18
/** Error code identifier */
19
code: ErrorCode;
20
21
/** Human-readable error message */
22
message: string;
23
24
/** Optional position information [start, end] */
25
pos?: [number, number];
26
27
constructor(pos: [number, number] | null, code: ErrorCode, message: string);
28
}
29
30
/**
31
* Parse-time errors with position information
32
*/
33
class YAMLParseError extends YAMLError {
34
/** Error name identifier */
35
name: 'YAMLParseError';
36
37
/** Position in source [start, end] */
38
pos: [number, number];
39
40
/** Line and column position */
41
linePos?: { line: number; col: number };
42
43
constructor(pos: [number, number], code: ErrorCode, message: string);
44
}
45
46
/**
47
* Warning messages for non-fatal issues
48
*/
49
class YAMLWarning extends YAMLError {
50
/** Warning name identifier */
51
name: 'YAMLWarning';
52
53
constructor(pos: [number, number] | null, code: ErrorCode, message: string);
54
}
55
```
56
57
### Error Codes
58
59
Comprehensive set of error codes covering all possible YAML parsing issues.
60
61
```typescript { .api }
62
type ErrorCode =
63
| 'BAD_ALIAS' // Invalid alias reference
64
| 'BAD_DIRECTIVE' // Invalid document directive
65
| 'BAD_DQ_ESCAPE' // Invalid escape sequence in double-quoted string
66
| 'BAD_INDENT' // Incorrect indentation
67
| 'BAD_PROP_ORDER' // Properties in wrong order
68
| 'BAD_SCALAR_START' // Invalid scalar start character
69
| 'BLOCK_AS_IMPLICIT_KEY' // Block scalar used as implicit key
70
| 'BLOCK_IN_FLOW' // Block scalar in flow context
71
| 'DUPLICATE_KEY' // Duplicate key in mapping
72
| 'IMPOSSIBLE' // Internal parser error
73
| 'KEY_OVER_1024_CHARS' // Key exceeds maximum length
74
| 'MISSING_CHAR' // Expected character missing
75
| 'MULTILINE_IMPLICIT_KEY' // Multiline implicit key
76
| 'MULTIPLE_ANCHORS' // Multiple anchors on single node
77
| 'MULTIPLE_DOCS' // Multiple documents in single-doc context
78
| 'MULTIPLE_TAGS' // Multiple tags on single node
79
| 'TAB_AS_INDENT' // Tab character used for indentation
80
| 'TAG_RESOLVE_FAILED' // Tag resolution failed
81
| 'UNEXPECTED_TOKEN'; // Unexpected token encountered
82
```
83
84
**Usage Examples:**
85
86
```typescript
87
import { parse, parseDocument, YAMLParseError, YAMLWarning } from "yaml";
88
89
// Handle parse errors
90
try {
91
const data = parse(`
92
invalid: [unclosed array
93
another: key
94
`);
95
} catch (error) {
96
if (error instanceof YAMLParseError) {
97
console.log('Parse Error Details:');
98
console.log('- Code:', error.code);
99
console.log('- Message:', error.message);
100
console.log('- Position:', error.pos);
101
console.log('- Line/Col:', error.linePos);
102
}
103
}
104
105
// Document-level error handling
106
const doc = parseDocument(`
107
key1: value1
108
key1: duplicate_value # DUPLICATE_KEY warning
109
invalid_alias: *nonexistent # BAD_ALIAS error
110
`);
111
112
// Check for errors
113
if (doc.errors.length > 0) {
114
console.log('Document Errors:');
115
doc.errors.forEach((error, index) => {
116
console.log(`${index + 1}. ${error.code}: ${error.message}`);
117
if (error.pos) {
118
console.log(` Position: ${error.pos[0]}-${error.pos[1]}`);
119
}
120
});
121
}
122
123
// Check for warnings
124
if (doc.warnings.length > 0) {
125
console.log('Document Warnings:');
126
doc.warnings.forEach((warning, index) => {
127
console.log(`${index + 1}. ${warning.code}: ${warning.message}`);
128
});
129
}
130
```
131
132
### Error Position Information
133
134
Errors include detailed position information for precise error location.
135
136
```typescript { .api }
137
interface LinePos {
138
/** Line number (1-based) */
139
line: number;
140
/** Column number (1-based) */
141
col: number;
142
}
143
144
type Range = [start: number, valueEnd: number, nodeEnd: number];
145
```
146
147
**Usage Examples:**
148
149
```typescript
150
import { parseDocument, prettifyError } from "yaml";
151
152
const source = `
153
name: John Doe
154
age: thirty # Invalid number
155
email: invalid-email # Missing @ symbol
156
items:
157
- item1
158
- item2
159
- nested_error # Invalid nesting
160
`;
161
162
const doc = parseDocument(source, { prettyErrors: true });
163
164
// Display errors with context
165
doc.errors.forEach(error => {
166
console.log('\n--- Error Details ---');
167
console.log('Code:', error.code);
168
console.log('Message:', error.message);
169
170
if (error.pos) {
171
console.log('Character range:', error.pos);
172
173
// Extract error context
174
const start = Math.max(0, error.pos[0] - 20);
175
const end = Math.min(source.length, error.pos[1] + 20);
176
const context = source.substring(start, end);
177
178
console.log('Context:', JSON.stringify(context));
179
}
180
181
if (error instanceof YAMLParseError && error.linePos) {
182
console.log(`Line ${error.linePos.line}, Column ${error.linePos.col}`);
183
}
184
});
185
```
186
187
### Error Formatting
188
189
Pretty error formatting with source context for better debugging experience.
190
191
```typescript { .api }
192
/**
193
* Add source context to error messages
194
* @param source - Original YAML source string
195
* @param lineCounter - Line position tracker
196
* @returns Function to format errors with context
197
*/
198
function prettifyError(source: string, lineCounter: LineCounter): (error: YAMLError) => void;
199
200
class LineCounter {
201
/**
202
* Add new line to position tracking
203
* @param offset - Character offset of new line
204
*/
205
addNewLine(offset: number): void;
206
207
/**
208
* Get line and column position for character offset
209
* @param pos - Character position
210
* @returns Line and column numbers
211
*/
212
linePos(pos: number): LinePos;
213
}
214
```
215
216
**Usage Examples:**
217
218
```typescript
219
import { parseDocument, prettifyError, LineCounter } from "yaml";
220
221
const source = `
222
config:
223
database:
224
host: localhost
225
port: "invalid_port" # Should be number
226
credentials:
227
username: admin
228
password: # Missing value
229
`;
230
231
// Parse with pretty errors enabled
232
const doc = parseDocument(source, {
233
prettyErrors: true,
234
lineCounter: true
235
});
236
237
// Errors are automatically prettified when prettyErrors: true
238
doc.errors.forEach(error => {
239
console.log(error.message); // Includes formatted context
240
});
241
242
// Manual error prettification
243
const lineCounter = new LineCounter();
244
const prettyFormatter = prettifyError(source, lineCounter);
245
246
// Simulate parsing with line counter
247
source.split('\n').forEach((line, index) => {
248
lineCounter.addNewLine(line.length + 1); // +1 for newline char
249
});
250
251
// Apply formatting to errors
252
doc.errors.forEach(prettyFormatter);
253
```
254
255
### Logging System
256
257
Configurable logging for controlling error and warning output.
258
259
```typescript { .api }
260
type LogLevelId = 'silent' | 'error' | 'warn' | 'debug';
261
262
/**
263
* Debug-level logging function
264
* @param logLevel - Current log level setting
265
* @param messages - Messages to log
266
*/
267
function debug(logLevel: LogLevelId, ...messages: any[]): void;
268
269
/**
270
* Warning-level logging function
271
* @param logLevel - Current log level setting
272
* @param messages - Messages to log
273
*/
274
function warn(logLevel: LogLevelId, ...messages: any[]): void;
275
```
276
277
**Usage Examples:**
278
279
```typescript
280
import { parseDocument, debug, warn } from "yaml";
281
282
// Configure logging levels
283
const quietDoc = parseDocument('key: value', {
284
logLevel: 'silent' // Suppress all output
285
});
286
287
const verboseDoc = parseDocument('key: value', {
288
logLevel: 'debug' // Show all messages
289
});
290
291
// Manual logging
292
warn('warn', 'This is a warning message');
293
debug('debug', 'This is a debug message', { additional: 'data' });
294
295
// Document with custom warning handling
296
const doc = parseDocument(`
297
key1: value1
298
key1: duplicate # Will generate warning
299
`);
300
301
// Process warnings manually
302
doc.warnings.forEach(warning => {
303
if (warning.code === 'DUPLICATE_KEY') {
304
console.log('Found duplicate key:', warning.message);
305
}
306
});
307
```
308
309
### Error Recovery
310
311
The library continues parsing even when errors are encountered, providing maximum information about document issues.
312
313
```typescript
314
import { parseDocument, parse } from "yaml";
315
316
// Malformed YAML with multiple errors
317
const malformedYaml = `
318
key1: value1
319
key2: [unclosed, array
320
key3:
321
nested: value
322
key2: duplicate
323
invalid_anchor_ref: *missing
324
key4: "unclosed string
325
`;
326
327
// parseDocument continues despite errors
328
const doc = parseDocument(malformedYaml);
329
330
console.log('Parsed content:', doc.toJS()); // Returns what could be parsed
331
console.log('Error count:', doc.errors.length);
332
console.log('Warning count:', doc.warnings.length);
333
334
// parse() throws on first error
335
try {
336
const data = parse(malformedYaml);
337
} catch (error) {
338
console.log('Parse failed:', error.message);
339
}
340
341
// Graceful error handling with fallback
342
function safeParseYaml(source: string, fallback: any = {}) {
343
try {
344
return parse(source);
345
} catch (error) {
346
console.warn('YAML parse failed, using fallback:', error.message);
347
return fallback;
348
}
349
}
350
351
const config = safeParseYaml(malformedYaml, { defaultConfig: true });
352
```
353
354
### Custom Error Handling
355
356
```typescript
357
import { parseDocument, YAMLError, YAMLParseError, YAMLWarning } from "yaml";
358
359
class YAMLProcessor {
360
private errors: YAMLError[] = [];
361
private warnings: YAMLWarning[] = [];
362
363
processDocument(source: string) {
364
const doc = parseDocument(source, { logLevel: 'silent' });
365
366
// Collect all issues
367
this.errors.push(...doc.errors);
368
this.warnings.push(...doc.warnings);
369
370
// Custom error categorization
371
const criticalErrors = this.errors.filter(e =>
372
['BAD_DIRECTIVE', 'IMPOSSIBLE'].includes(e.code)
373
);
374
375
const minorErrors = this.errors.filter(e =>
376
['DUPLICATE_KEY', 'TAB_AS_INDENT'].includes(e.code)
377
);
378
379
// Report based on severity
380
if (criticalErrors.length > 0) {
381
throw new Error(`Critical YAML errors: ${criticalErrors.length}`);
382
}
383
384
if (minorErrors.length > 0) {
385
console.warn(`Minor YAML issues: ${minorErrors.length}`);
386
}
387
388
return doc;
389
}
390
391
getErrorReport() {
392
return {
393
totalErrors: this.errors.length,
394
totalWarnings: this.warnings.length,
395
errorsByCode: this.groupByCode(this.errors),
396
warningsByCode: this.groupByCode(this.warnings)
397
};
398
}
399
400
private groupByCode(issues: YAMLError[]) {
401
return issues.reduce((acc, issue) => {
402
acc[issue.code] = (acc[issue.code] || 0) + 1;
403
return acc;
404
}, {} as Record<string, number>);
405
}
406
}
407
408
// Usage
409
const processor = new YAMLProcessor();
410
try {
411
const doc = processor.processDocument(malformedYaml);
412
console.log('Processing completed with warnings');
413
} catch (error) {
414
console.error('Processing failed:', error.message);
415
}
416
417
console.log('Error report:', processor.getErrorReport());
418
```