Bird
Raised Fist0
Expressframework~20 mins

Custom validation rules in Express - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
Express Validation Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What is the output of this Express middleware with custom validation?
Consider this Express middleware that validates a request body property 'age' to be a number greater than 18. What response will the server send if the request body is {"age": 16}?
Express
app.post('/check-age', (req, res, next) => {
  const age = req.body.age;
  if (typeof age !== 'number' || age <= 18) {
    return res.status(400).json({ error: 'Age must be a number greater than 18' });
  }
  next();
}, (req, res) => {
  res.json({ message: 'Age is valid' });
});
AStatus 400 with JSON { error: 'Invalid request body' }
BStatus 200 with JSON { message: 'Age is valid' }
CStatus 500 with JSON { error: 'Server error' }
DStatus 400 with JSON { error: 'Age must be a number greater than 18' }
Attempts:
2 left
💡 Hint
Think about the condition that checks the age value and what happens when it fails.
📝 Syntax
intermediate
2:00remaining
Which option correctly defines a custom validation function in Express?
You want to create a custom validation function to check if a string is uppercase. Which code snippet correctly defines and uses this function in Express middleware?
Afunction isUpperCase(str) { return str === str.toUpperCase(); } app.use((req, res, next) => { if (!isUpperCase(req.body.name)) return res.status(400).send('Name must be uppercase'); next(); });
Bconst isUpperCase = (str) => { str.toUpperCase(); }; app.use((req, res, next) => { if (!isUpperCase(req.body.name)) return res.status(400).send('Name must be uppercase'); next(); });
Cfunction isUpperCase(str) { return str.toLowerCase() === str; } app.use((req, res, next) => { if (!isUpperCase(req.body.name)) return res.status(400).send('Name must be uppercase'); next(); });
Dconst isUpperCase = str => { return str.toUpperCase === str; }; app.use((req, res, next) => { if (!isUpperCase(req.body.name)) return res.status(400).send('Name must be uppercase'); next(); });
Attempts:
2 left
💡 Hint
Check if the function returns a boolean and compares correctly.
🔧 Debug
advanced
2:00remaining
Why does this custom validation middleware always pass even with invalid input?
This middleware is supposed to reject requests where 'email' is missing or invalid. Why does it allow invalid emails?
Express
app.use((req, res, next) => {
  const email = req.body.email;
  if (!email && !email.includes('@')) {
    return res.status(400).send('Invalid email');
  }
  next();
});
ABecause next() is called before the condition, so validation is skipped.
BBecause email.includes('@') throws an error if email is undefined, so middleware crashes silently.
CBecause the condition uses && instead of ||, so it only fails if email is falsy AND includes '@', which never happens.
DBecause res.status(400).send() is asynchronous and does not stop middleware execution.
Attempts:
2 left
💡 Hint
Look carefully at the if condition combining !email and !email.includes('@').
state_output
advanced
2:00remaining
What is the value of req.customData after this validation middleware runs?
This middleware adds a customData property to req if validation passes. What is req.customData after a request with body { username: 'User123' }?
Express
app.use((req, res, next) => {
  const username = req.body.username;
  if (typeof username === 'string' && username.length >= 5) {
    req.customData = { valid: true, user: username.toLowerCase() };
  } else {
    req.customData = { valid: false };
  }
  next();
});
A{ valid: false }
B{ valid: true, user: 'user123' }
Cundefined
Dnull
Attempts:
2 left
💡 Hint
Check the username length and type, then see what customData is set to.
🧠 Conceptual
expert
2:00remaining
Which option best explains why custom validation middleware should call next() only once?
In Express, why must custom validation middleware call next() exactly once and not multiple times or skip it?
ACalling next() multiple times causes the request to be processed by multiple handlers repeatedly, leading to errors or crashes.
BCalling next() multiple times improves performance by parallelizing middleware execution.
CSkipping next() causes the server to automatically retry the request, causing infinite loops.
DSkipping next() causes the response to be sent twice, which is allowed but not recommended.
Attempts:
2 left
💡 Hint
Think about how Express middleware chains work and what happens if next() is called more than once.

Practice

(1/5)
1. What is the main purpose of using custom() in Express validation?
easy
A. To format the response JSON
B. To automatically sanitize all inputs
C. To connect to the database
D. To create your own rules for checking input values

Solution

  1. Step 1: Understand the role of custom()

    The custom() method allows you to write your own validation logic beyond built-in checks.
  2. Step 2: Identify the purpose in input validation

    It is used to check inputs with rules you define, like checking a password strength or a special format.
  3. Final Answer:

    To create your own rules for checking input values -> Option D
  4. Quick Check:

    Custom validation = custom rules [OK]
Hint: Custom means you write your own check function [OK]
Common Mistakes:
  • Thinking custom() sanitizes inputs automatically
  • Confusing custom() with response formatting
  • Assuming custom() connects to databases
2. Which of the following is the correct syntax to add a custom validation rule using Express Validator?
easy
A. check('age').custom(value => { if(value < 18) throw new Error('Too young'); return true; })
B. check('age').custom(value => value < 18 ? true : false)
C. check('age').custom(value => { return false; })
D. check('age').custom(value => { throw 'Error'; })

Solution

  1. Step 1: Review correct custom validation syntax

    The function inside custom() should throw an error if validation fails and return true if it passes.
  2. Step 2: Analyze each option

    check('age').custom(value => { if(value < 18) throw new Error('Too young'); return true; }) throws an error when value is less than 18 and returns true otherwise, which is correct. check('age').custom(value => value < 18 ? true : false) returns true when value is less than 18, which is opposite logic. check('age').custom(value => { return false; }) always returns false, which fails validation. check('age').custom(value => { throw 'Error'; }) throws an error unconditionally, so it always fails.
  3. Final Answer:

    check('age').custom(value => { if(value < 18) throw new Error('Too young'); return true; }) -> Option A
  4. Quick Check:

    Throw error on fail, return true on pass [OK]
Hint: Throw error to fail, return true to pass [OK]
Common Mistakes:
  • Returning false instead of throwing error
  • Throwing error without condition
  • Returning true on invalid input
3. Given this code snippet, what will be the validation result if req.body.username is "abc"?
check('username').custom(value => {
  if(value.length < 5) throw new Error('Too short');
  return true;
})
medium
A. Validation fails with 'Too short' error
B. Validation passes
C. Validation fails with syntax error
D. Validation passes but logs a warning

Solution

  1. Step 1: Check the input value length

    The input "abc" has length 3, which is less than 5.
  2. Step 2: Apply the custom validation logic

    The function throws an error 'Too short' if length is less than 5, so it throws an error here causing validation to fail.
  3. Final Answer:

    Validation fails with 'Too short' error -> Option A
  4. Quick Check:

    Input too short = error thrown [OK]
Hint: Check input length against condition in custom() [OK]
Common Mistakes:
  • Assuming validation passes for short input
  • Confusing error throwing with warnings
  • Expecting syntax errors from valid code
4. Identify the error in this custom validation code:
check('email').custom(value => {
  if(!value.includes('@'))
    return new Error('Invalid email');
  return true;
})
medium
A. The function must return false instead of true
B. The condition should check for '.' instead of '@'
C. It should throw an error, not return it
D. No error, code is correct

Solution

  1. Step 1: Understand error signaling in custom validation

    Custom validators must throw an error to indicate failure, not return an Error object.
  2. Step 2: Analyze the given code

    The code returns new Error('Invalid email') instead of throwing it, so validation will not fail as expected.
  3. Final Answer:

    It should throw an error, not return it -> Option C
  4. Quick Check:

    Throw error to fail validation [OK]
Hint: Throw errors, don't return them in custom() [OK]
Common Mistakes:
  • Returning Error object instead of throwing
  • Checking wrong condition for email
  • Returning false instead of throwing error
5. You want to create a custom validation rule that checks if a password contains at least one uppercase letter, one number, and is at least 8 characters long. Which of these implementations correctly achieves this?
hard
A. check('password').custom(value => { if(value.length < 8) return false; if(!/[A-Z]/.test(value)) return false; if(!/\d/.test(value)) return false; return true; })
B. check('password').custom(value => { if(!/[A-Z]/.test(value)) throw new Error('Missing uppercase'); if(!/\d/.test(value)) throw new Error('Missing number'); if(value.length < 8) throw new Error('Too short'); return true; })
C. check('password').custom(value => { if(value.length < 8) throw 'Too short'; if(!/[A-Z]/.test(value)) throw 'Missing uppercase'; if(!/\d/.test(value)) throw 'Missing number'; return false; })
D. check('password').custom(value => { if(value.length >= 8 && /[A-Z]/.test(value) && /\d/.test(value)) return true; else return false; })

Solution

  1. Step 1: Check each condition with proper error throwing

    check('password').custom(value => { if(!/[A-Z]/.test(value)) throw new Error('Missing uppercase'); if(!/\d/.test(value)) throw new Error('Missing number'); if(value.length < 8) throw new Error('Too short'); return true; }) checks each condition separately and throws a specific error if it fails, returning true only if all pass.
  2. Step 2: Compare other options for correctness

    check('password').custom(value => { if(value.length < 8) return false; if(!/[A-Z]/.test(value)) return false; if(!/\d/.test(value)) return false; return true; }) returns false instead of throwing errors, which is incorrect. check('password').custom(value => { if(value.length < 8) throw 'Too short'; if(!/[A-Z]/.test(value)) throw 'Missing uppercase'; if(!/\d/.test(value)) throw 'Missing number'; return false; }) throws string errors and returns false at the end, which breaks the rule of returning true on success. check('password').custom(value => { if(value.length >= 8 && /[A-Z]/.test(value) && /\d/.test(value)) return true; else return false; }) returns false instead of throwing an error if conditions fail, which is incorrect.
  3. Final Answer:

    check('password').custom(value => { if(!/[A-Z]/.test(value)) throw new Error('Missing uppercase'); if(!/\d/.test(value)) throw new Error('Missing number'); if(value.length < 8) throw new Error('Too short'); return true; }) -> Option B
  4. Quick Check:

    Throw specific errors, return true if all pass [OK]
Hint: Throw specific errors for each fail, return true if all pass [OK]
Common Mistakes:
  • Returning false instead of throwing errors
  • Throwing strings instead of Error objects
  • Returning false on success