Lesson 3 of 7 · 11 min · 2 hands-on steps
Validating Input & Handling Errors
Never trust what clients send. Validate everything and fail with clear messages.
Rule #1 of back-end work: never trust the client
Anyone can send any request to your API with tools like curl, skipping your nice front-end form. Every input must be checked on the server.
Validate early, report everything
function validateComment(body) {
const errors = [];
if (typeof body.text !== "string" || !body.text.trim()) errors.push("Text is required");
if (body.text && body.text.length > 500) errors.push("Text must be 500 characters or fewer");
return errors;
}
console.log(validateComment({ text: "" }));
console.log(validateComment({ text: "Great lesson!" }));Returning all problems at once lets the form show every error together, instead of making users fix one at a time.
Pick the right status code
| Situation | Status |
|---|---|
| Input is malformed or invalid | 400 Bad Request |
| Not logged in | 401 Unauthorized |
| Logged in, but not allowed | 403 Forbidden |
| Doesn't exist | 404 Not Found |
| Conflicts with existing data (duplicate email) | 409 Conflict |
| Too many requests | 429 Too Many Requests |
| Your code crashed | 500 Internal Server Error |
Don't leak secrets in errors or responses
- Never return passwords (even hashed) in API responses
- Don't send stack traces to users in production. Log them on the server instead.
- For login failures, say "Incorrect email or password", not which one was wrong (that tells attackers which emails exist)
This site's own sign-up follows every one of these rules.
🧪 Practice: 2 steps
0 / 2 doneStep 1 of 2 · Validate a sign-up
Write validateSignup(body) that returns an array of error messages (empty if valid):
"Name is required"ifnameis missing or blank"Email is invalid"ifemaildoesn't look likex@y.z"Password must be at least 8 characters"if too short
Report all problems at once, in that order.
function validateSignup(body) {
const errors = [];
return errors;
}
Output appears here. Press Run or Ctrl/⌘ + Enter.
Step 2 of 2 · A safe handler
Write createUser(body, users) that:
- returns
{ status: 400, body: { errors } }ifvalidateSignupfinds problems - returns
{ status: 409, body: { error: "Email already registered" } }if a user with that email (case-insensitive) exists - otherwise adds
{ id, name, email }tousers(id = users.length + 1), and returns{ status: 201, body: thatUser }. Never put the password in the response.
function validateSignup(body) {
const errors = [];
if (!body.name || !String(body.name).trim()) errors.push("Name is required");
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(body.email || "")) errors.push("Email is invalid");
if (!body.password || body.password.length < 8) errors.push("Password must be at least 8 characters");
return errors;
}
function createUser(body, users) {
}
Output appears here. Press Run or Ctrl/⌘ + Enter.
✅ Check your understanding
Your front end already validates the form. Should the server validate too?
Create a free account to track your progress.