Why Error Handling Testing Matters

Users will inevitably encounter errors — they will visit deleted pages, submit invalid forms, experience network timeouts, and trigger server failures. How your application handles these errors determines whether users stay or leave, whether they trust your product, and whether attackers can exploit error responses.

Error handling is one of the most frequently overlooked testing areas. Developers focus on the happy path, and errors are often tested last (if at all). This creates opportunities for QA to find impactful bugs.

HTTP Status Code Categories

RangeCategoryMeaning
2xxSuccessRequest completed successfully
3xxRedirectionClient must take additional action
4xxClient ErrorRequest was invalid
5xxServer ErrorServer failed to fulfill a valid request

Key Status Codes to Test

CodeMeaningWhen to Test
200OKEvery successful request
301Moved PermanentlyURL migrations, HTTPS redirects
302/307Temporary RedirectLogin redirects, locale redirects
400Bad RequestMalformed request data
401UnauthorizedMissing or invalid authentication
403ForbiddenValid auth but insufficient permissions
404Not FoundNon-existent URLs
405Method Not AllowedWrong HTTP method (GET vs POST)
408Request TimeoutSlow requests
429Too Many RequestsRate limiting
500Internal Server ErrorUnhandled server exceptions
502Bad GatewayUpstream server failures
503Service UnavailableMaintenance, overload
504Gateway TimeoutUpstream server timeout

Testing Custom Error Pages

404 Not Found Page

The most common error users encounter. Test that:

  • Visiting a non-existent URL shows a custom 404 page (not a generic server error)
  • The page maintains site branding (header, footer, styles)
  • Navigation is available to help the user find what they need
  • A search bar is present
  • Links to popular pages or the homepage are provided
  • The correct 404 HTTP status code is returned (not 200)
  • The page works in all supported languages

500 Internal Server Error Page

  • A friendly message is shown without technical details
  • No stack traces, database errors, or file paths are visible
  • Contact information or support link is provided
  • The page suggests trying again later
  • Monitoring/alerting triggers on 500 errors

403 Forbidden Page

  • Explains that access is denied without revealing why (do not say “this resource belongs to another user”)
  • Suggests logging in if the user is not authenticated
  • Provides a link to request access if applicable

Maintenance Page (503)

  • Clear message about maintenance in progress
  • Expected return time if known
  • Contact information for urgent issues
  • Works without JavaScript (the app may be completely down)

Form Validation Error Testing

Client-Side Validation

ScenarioExpected Behavior
Required field empty“This field is required” near the field
Invalid email format“Please enter a valid email address”
Password too short“Password must be at least 8 characters”
Mismatched passwords“Passwords do not match”
Invalid date“Please enter a valid date”
Number out of range“Value must be between X and Y”

Server-Side Validation

Client-side validation can be bypassed. Test that:

  • Disabling JavaScript and submitting forms still shows validation errors
  • Submitting requests directly via API returns proper error messages
  • Error messages do not reveal system internals

Error Message Quality

Good error messages:

  • Tell the user what went wrong
  • Tell the user how to fix it
  • Are positioned near the problematic field
  • Are announced to screen readers (using aria-live or role="alert")
  • Do not disappear too quickly

Bad error messages:

  • “An error occurred” (too vague)
  • “Error code: NullPointerException at UserService.java:142” (too technical)
  • “Invalid input” (does not say what is invalid or how to fix it)

Security Considerations

What Error Responses Must NOT Reveal

DangerExample
Stack tracesjava.lang.NullPointerException at com.app.UserService.getUser(UserService.java:142)
Database errorsERROR: column "email" of relation "users" does not exist
File pathsFileNotFoundException: /var/www/app/config/database.yml
Server versionsApache/2.4.41 (Ubuntu) Server
Internal IPsConnection refused to 10.0.1.42:5432

Error Enumeration Prevention

  • Login errors should say “Invalid email or password” (not “Email not found” or “Wrong password”)
  • Registration should not confirm whether an email is already in use
  • Password reset should not confirm whether an email exists in the system

Exercise: Error Handling Audit

Test the error handling of a web application across all major error categories.

Part 1: HTTP Error Pages

TestURL/ActionExpectedActualStatus
404 pageVisit /nonexistent-page-xyzCustom 404 with navigation
404 returns correct statusCheck response codeHTTP 404 (not 200)
404 in other languagesVisit /es/nonexistent-page404 in correct language
403 pageAccess admin without authCustom 403 or redirect to login
500 pageTrigger server errorCustom 500 without stack trace

Part 2: Form Validation

Choose a form (registration, checkout, or contact) and test:

InputValueExpected Error Message
Emailempty“Email is required”
Email“not-an-email”“Please enter a valid email”
Emailexisting email“An account with this email already exists” (or neutral message)
Password“123”“Password must be at least 8 characters”
Password“password”Weak password warning
Phone“abc”“Please enter a valid phone number”
Required fieldskip it“This field is required”

Part 3: Error Message Security

CheckPass/Fail
No stack traces in any error response
No database error messages visible to users
No file paths in error responses
No server version in headers or error pages
Login error does not reveal if email exists
API errors return generic messages
Solution: Common Error Handling Bugs

Bug 1: 404 page returns HTTP 200 The custom 404 page was served with a 200 status code. Search engines indexed “not found” pages as real content. Fix: Ensure the server returns HTTP 404 status with the custom page.

Bug 2: Stack trace visible on production 500 error A server error revealed the full Java stack trace including class names, method names, and line numbers. Fix: Configure production to show a generic error page and log details server-side only.

Bug 3: Form validation errors disappeared on scroll Validation errors at the top of a long form disappeared when the user scrolled down to fix the issue. Fix: Keep errors visible and scroll to the first error on submit.

Bug 4: Login reveals email existence “No account found with this email” on login reveals that the email is not registered, helping attackers enumerate valid accounts. Fix: Use “Invalid email or password” for all login failures.

Bug 5: API error returns SQL query A malformed API request returned: ERROR: syntax error at or near "DROP" at character 42. Fix: Catch database errors and return generic API error messages.

Bug 6: Error page has no navigation The 404 page showed only “Page not found” with no links, header, or search. Users had to manually type the URL. Fix: Include full site navigation on error pages.

Automation for Error Handling

test('404 page returns correct status code', async ({ page }) => {
  const response = await page.goto('/this-page-does-not-exist');
  expect(response.status()).toBe(404);
  await expect(page.locator('nav')).toBeVisible(); // Navigation present
  await expect(page.locator('a[href="/"]')).toBeVisible(); // Home link
});

test('API errors do not leak internals', async ({ request }) => {
  const response = await request.get('/api/users/invalid-id');
  const body = await response.json();
  expect(body.message).not.toContain('Exception');
  expect(body.message).not.toContain('.java');
  expect(body.message).not.toContain('SELECT');
});

Key Takeaways

  • Error handling is frequently undertested — make it a standard part of your test plan
  • Custom error pages should maintain site branding and provide navigation options
  • Error messages must be user-friendly: explain the problem and how to fix it
  • Never expose technical details in production error responses — stack traces, SQL, file paths
  • Prevent information leakage through error responses (login enumeration, email existence)
  • Verify that HTTP status codes match the error type (404 should return 404, not 200)