or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-interface.mderror-handling.mdindex.mdsimple-api.mdsitemap-index.mdsitemap-parsing.mdsitemap-streams.mdvalidation-utilities.mdxml-validation.md

error-handling.mddocs/

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

```