BugForge
All lessons
Databases · 09/09 5 min1 hands-on

Database errors to status codes

ValidationError, duplicate keys and CastError: turn each into the right 4xx, and never leak the password.

When the database says no, it throws. Your job is to translate that into a status code the client understands, instead of a blanket 500.

The translation table

What happened How to spot it Status
broke a schema rule (required, minlength, enum) err.name === "ValidationError" 400
unique field already taken err.code === 11000 409
malformed id passed to findById err.name === "CastError" 400
query found nothing result is null 404
anything else 500
try {
  const user = await User.create({ email, password });
  res.status(201).json({ id: user._id, email: user.email });
} catch (err) {
  if (err.name === "ValidationError") return res.status(400).json({ error: err.message });
  if (err.code === 11000) return res.status(409).json({ error: "Email already registered" });
  res.status(500).json({ error: "Something went wrong" });
}

Unique means unique… after normalising

Ada@Example.com and ada@example.com are the same person. lowercase: true and trim: true on the schema make the unique index catch that.

Never send the password back

res.json(user) sends every field, password included. Pick the fields you return, or strip sensitive ones. Tests check for this with not.toHaveProperty("password").

Don't trust the body

User.create(req.body) saves whatever the client sends, including role: "admin". Copy the fields you expect: const { email, password } = req.body.

Your turn · 1 exercise0/1 solved

Turn database errors into status codes

POST /users creates a user (201). A validation failure is 400, a duplicate email is 409, and the password never comes back in the response.

Loading editor…
Next in Databases
Mongoose & MongoDB essentials