DevPath · Learn to code ESPTEN

Errors and robust validation

Robust input validation

Never trust input

All input coming from the client (req.body, req.query, req.params) is untrusted data. Before using it you must:

  1. Validate: check that it meets the rules (fields present, correct types, valid ranges).
  2. Sanitize: normalize and clean (trim whitespace, lowercase an email, discard extra fields).
function validateUser(data) {
  const errors = [];
  if (!data.email) errors.push("Email is missing");
  if (typeof data.age !== "number" || data.age < 0) {
    errors.push("Age must be a non-negative number");
  }
  return errors;
}

Schemas (Zod / Joi, conceptual)

Validating by hand becomes repetitive. Schema libraries declare the expected shape of the data once and validate against it:

// Conceptual (Zod):
// const User = z.object({
//   email: z.string().email(),
//   age: z.number().int().nonnegative(),
// });
// const result = User.safeParse(data);

The schema describes what is expected, not how to check it step by step. Joi offers an equivalent idea with different syntax.

Respond 400 with clear details

When validation fails, respond with 400 (Bad Request) and include what failed, so the client can fix it:

const errors = validateUser(req.body);
if (errors.length > 0) {
  return res.status(400).json({ error: "Invalid data", details: errors });
}

Returning a list of errors (instead of stopping at the first one) is more useful: the client sees all the problems at once.

Examples

validateUser returns the list of problems

function validateUser(data) {
  const errors = [];
  if (!data.email) errors.push("Email is missing");
  if (typeof data.age !== "number" || data.age < 0) {
    errors.push("Age must be a non-negative number");
  }
  return errors;
}

console.log(validateUser({ email: "a@b.com", age: 30 })); // []
console.log(validateUser({ age: -1 }));                    // 2 errors
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Custom error classesView the module →