or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-schemas.mdcoercion.mdcollections.mderrors.mdindex.mdiso-datetime.mdjson-schema.mdlocales.mdnumber-formats.mdparsing.mdprimitives.mdrefinements.mdstring-formats.mdtransformations.mdunions-intersections.mdutilities.mdwrappers.md

errors.mddocs/

0

# Error Handling

1

2

Structured error types with granular issue reporting and formatting utilities.

3

4

## ZodError Class

5

6

```typescript { .api }

7

/**

8

* Main error class for Zod validation failures

9

*/

10

class ZodError<T = any> extends Error {

11

/** Array of validation issues */

12

issues: ZodIssue[];

13

14

/** Alias for issues (deprecated) */

15

errors: ZodIssue[];

16

17

/** Error name (always "ZodError") */

18

name: "ZodError";

19

20

/** Formatted error message */

21

message: string;

22

23

constructor(issues: ZodIssue[]);

24

25

/**

26

* Format error as tree structure matching data shape

27

* @param mapper - Optional function to transform issues

28

* @returns Formatted error tree with _errors arrays at each level

29

*/

30

format<U = string>(mapper?: (issue: ZodIssue) => U): ZodFormattedError<T, U>;

31

32

/**

33

* Flatten error structure into form and field errors

34

* @param mapper - Optional function to transform issues

35

* @returns Flattened error object with formErrors and fieldErrors

36

*/

37

flatten<U = string>(mapper?: (issue: ZodIssue) => U): ZodFlattenedError<U>;

38

39

/**

40

* String representation of error

41

* @returns Error string with all issues listed

42

*/

43

toString(): string;

44

45

/**

46

* Add issue to error (deprecated)

47

* @param issue - Issue to add

48

*/

49

addIssue(issue: ZodIssue): void;

50

51

/**

52

* Add multiple issues (deprecated)

53

* @param issues - Issues to add

54

*/

55

addIssues(issues: ZodIssue[]): void;

56

57

/** Check if error has no issues */

58

get isEmpty(): boolean;

59

60

/** Get error as JSON (alias for issues) */

61

get errors(): ZodIssue[];

62

}

63

64

interface ZodFormattedError<T = any, U = string> {

65

_errors: U[];

66

[key: string]: ZodFormattedError<any, U> | U[];

67

}

68

69

interface ZodFlattenedError<U = string> {

70

formErrors: U[];

71

fieldErrors: { [k: string]: U[] };

72

}

73

```

74

75

**Examples:**

76

```typescript

77

try {

78

UserSchema.parse(invalidData);

79

} catch (error) {

80

if (error instanceof z.ZodError) {

81

// Access issues

82

console.log(error.issues);

83

84

// Format as tree

85

const formatted = error.format();

86

// { _errors: [], name: { _errors: ["Too short"] }, ... }

87

88

// Flatten errors

89

const flattened = error.flatten();

90

// { formErrors: [], fieldErrors: { name: ["Too short"], ... } }

91

92

// String representation

93

console.log(error.toString());

94

console.log(error.message);

95

96

// Check if empty

97

console.log(error.isEmpty); // false

98

}

99

}

100

```

101

102

## ZodIssue Types

103

104

```typescript { .api }

105

interface ZodIssue {

106

code: ZodIssueCode;

107

path: (string | number)[];

108

message: string;

109

}

110

111

enum ZodIssueCode {

112

invalid_type = "invalid_type",

113

invalid_literal = "invalid_literal",

114

custom = "custom",

115

invalid_union = "invalid_union",

116

invalid_union_discriminator = "invalid_union_discriminator",

117

invalid_enum_value = "invalid_enum_value",

118

unrecognized_keys = "unrecognized_keys",

119

invalid_arguments = "invalid_arguments",

120

invalid_return_type = "invalid_return_type",

121

invalid_date = "invalid_date",

122

invalid_string = "invalid_string",

123

too_small = "too_small",

124

too_big = "too_big",

125

invalid_intersection_types = "invalid_intersection_types",

126

not_multiple_of = "not_multiple_of",

127

not_finite = "not_finite",

128

}

129

130

// Specific issue types

131

interface ZodInvalidTypeIssue extends ZodIssue {

132

code: "invalid_type";

133

expected: ZodParsedType;

134

received: ZodParsedType;

135

}

136

137

interface ZodTooSmallIssue extends ZodIssue {

138

code: "too_small";

139

type: "string" | "number" | "bigint" | "array" | "set" | "date";

140

minimum: number | bigint;

141

inclusive: boolean;

142

exact?: boolean;

143

}

144

145

interface ZodTooBigIssue extends ZodIssue {

146

code: "too_big";

147

type: "string" | "number" | "bigint" | "array" | "set" | "date";

148

maximum: number | bigint;

149

inclusive: boolean;

150

exact?: boolean;

151

}

152

153

interface ZodCustomIssue extends ZodIssue {

154

code: "custom";

155

params?: { [k: string]: any };

156

}

157

158

interface ZodInvalidStringIssue extends ZodIssue {

159

code: "invalid_string";

160

validation: "email" | "url" | "uuid" | "regex" | "datetime" | "ip"

161

| { includes: string; position?: number }

162

| { startsWith: string }

163

| { endsWith: string };

164

}

165

166

interface ZodInvalidUnionIssue extends ZodIssue {

167

code: "invalid_union";

168

unionErrors: ZodError[];

169

}

170

171

interface ZodInvalidEnumValueIssue extends ZodIssue {

172

code: "invalid_enum_value";

173

options: any[];

174

received: any;

175

}

176

177

interface ZodUnrecognizedKeysIssue extends ZodIssue {

178

code: "unrecognized_keys";

179

keys: string[];

180

}

181

182

interface ZodInvalidLiteralIssue extends ZodIssue {

183

code: "invalid_literal";

184

expected: any;

185

received: any;

186

}

187

188

interface ZodInvalidUnionDiscriminatorIssue extends ZodIssue {

189

code: "invalid_union_discriminator";

190

options: any[];

191

}

192

193

interface ZodInvalidArgumentsIssue extends ZodIssue {

194

code: "invalid_arguments";

195

argumentsError: ZodError;

196

}

197

198

interface ZodInvalidReturnTypeIssue extends ZodIssue {

199

code: "invalid_return_type";

200

returnTypeError: ZodError;

201

}

202

203

interface ZodInvalidDateIssue extends ZodIssue {

204

code: "invalid_date";

205

}

206

207

interface ZodInvalidIntersectionTypesIssue extends ZodIssue {

208

code: "invalid_intersection_types";

209

}

210

211

interface ZodNotMultipleOfIssue extends ZodIssue {

212

code: "not_multiple_of";

213

multipleOf: number | bigint;

214

}

215

216

interface ZodNotFiniteIssue extends ZodIssue {

217

code: "not_finite";

218

}

219

220

type ZodParsedType =

221

| "string" | "number" | "bigint" | "boolean" | "date" | "symbol"

222

| "undefined" | "null" | "array" | "object" | "map" | "set"

223

| "function" | "promise" | "nan" | "unknown";

224

```

225

226

## Error Formatting

227

228

```typescript { .api }

229

/**

230

* Format error as tree structure matching data shape

231

* @param error - ZodError to format

232

* @param mapper - Optional function to transform issues

233

* @returns Formatted error tree with _errors arrays at each level

234

*/

235

function formatError<T = any, U = string>(

236

error: ZodError<T>,

237

mapper?: (issue: ZodIssue) => U

238

): ZodFormattedError<T, U>;

239

240

/**

241

* Flatten error structure into form and field errors

242

* @param error - ZodError to flatten

243

* @param mapper - Optional function to transform issues

244

* @returns Flattened error object with formErrors and fieldErrors

245

*/

246

function flattenError<U = string>(

247

error: ZodError,

248

mapper?: (issue: ZodIssue) => U

249

): ZodFlattenedError<U>;

250

251

/**

252

* Format error as tree (alias for formatError)

253

* @param error - ZodError to format

254

* @param mapper - Optional function to transform issues

255

* @returns Formatted error tree

256

*/

257

function treeifyError<T = any, U = string>(

258

error: ZodError<T>,

259

mapper?: (issue: ZodIssue) => U

260

): ZodFormattedError<T, U>;

261

262

/**

263

* Pretty-print error as readable string

264

* @param error - ZodError to prettify

265

* @returns Formatted error string with path: message format

266

*/

267

function prettifyError(error: ZodError): string;

268

```

269

270

**Examples:**

271

```typescript

272

const result = ComplexSchema.safeParse(data);

273

274

if (!result.success) {

275

const error = result.error;

276

277

// Format as tree

278

const formatted = error.format();

279

// {

280

// _errors: [],

281

// name: { _errors: ["Too short"] },

282

// age: { _errors: ["Must be positive"] },

283

// address: {

284

// _errors: [],

285

// street: { _errors: ["Required"] }

286

// }

287

// }

288

289

// Flatten errors

290

const flattened = error.flatten();

291

// {

292

// formErrors: [],

293

// fieldErrors: {

294

// name: ["Too short"],

295

// age: ["Must be positive"],

296

// "address.street": ["Required"]

297

// }

298

// }

299

300

// Custom mapper

301

const customFormatted = error.format((issue) => ({

302

code: issue.code,

303

message: issue.message,

304

}));

305

306

// Prettify

307

const pretty = z.prettifyError(error);

308

// name: Too short

309

// age: Must be positive

310

// address.street: Required

311

}

312

```

313

314

## Error Handling Patterns

315

316

```typescript

317

// Pattern 1: Try-catch with parse

318

try {

319

const data = schema.parse(input);

320

// Use data

321

} catch (error) {

322

if (error instanceof z.ZodError) {

323

console.error(error.issues);

324

}

325

}

326

327

// Pattern 2: Safe parse (preferred)

328

const result = schema.safeParse(input);

329

if (!result.success) {

330

console.error(result.error.issues);

331

} else {

332

// Use result.data

333

}

334

335

// Pattern 3: Express middleware

336

function validateBody(schema: z.ZodSchema) {

337

return (req, res, next) => {

338

const result = schema.safeParse(req.body);

339

if (!result.success) {

340

return res.status(400).json({

341

errors: result.error.flatten().fieldErrors,

342

});

343

}

344

req.validatedBody = result.data;

345

next();

346

};

347

}

348

349

// Pattern 4: Issue inspection

350

const result = schema.safeParse(input);

351

if (!result.success) {

352

result.error.issues.forEach((issue) => {

353

switch (issue.code) {

354

case z.ZodIssueCode.invalid_type:

355

console.log(`Expected ${issue.expected}, got ${issue.received}`);

356

break;

357

case z.ZodIssueCode.too_small:

358

console.log(`Value too small: minimum is ${issue.minimum}`);

359

break;

360

case z.ZodIssueCode.custom:

361

console.log(`Custom validation failed: ${issue.message}`);

362

break;

363

}

364

});

365

}

366

367

// Pattern 5: Form validation

368

function validateForm(formData: FormData) {

369

const result = FormSchema.safeParse(

370

Object.fromEntries(formData.entries())

371

);

372

373

if (!result.success) {

374

const errors = result.error.flatten().fieldErrors;

375

// Display errors in form

376

return { success: false, errors };

377

}

378

379

return { success: true, data: result.data };

380

}

381

382

// Pattern 6: API response

383

async function handleRequest(body: unknown) {

384

const result = await schema.safeParseAsync(body);

385

386

if (!result.success) {

387

return {

388

status: 400,

389

errors: result.error.format(),

390

};

391

}

392

393

return {

394

status: 200,

395

data: result.data,

396

};

397

}

398

```

399

400

## Custom Error Messages

401

402

```typescript

403

// Custom error messages

404

const schema = z

405

.string()

406

.min(5, "Too short!")

407

.max(20, "Too long!");

408

409

// Error map for all issues

410

const customSchema = z.string().parse(data, {

411

errorMap: (issue, ctx) => {

412

if (issue.code === z.ZodIssueCode.too_small) {

413

return { message: "Custom message for too_small" };

414

}

415

return { message: ctx.defaultError };

416

},

417

});

418

419

// Global error map

420

z.config({

421

errorMap: (issue, ctx) => {

422

// Custom global error mapping

423

return { message: ctx.defaultError };

424

},

425

});

426

```

427