Skip to content

Server Errors

DodaTech 2 min read

title: "Server Errors — Handling 500, 502, 503 Responses" description: "Server errors (5xx) indicate the server failed to fulfill a valid request, with 500 for internal errors, 502 for bad gateways, and 503 for service unavailability." date: 2026-06-28 lastmod: 2026-06-28 weight: 20 tags: [apis, error-handling] }

Server errors (5xx) occur when the server cannot fulfill a valid request due to internal failures, upstream service issues, or temporary overload.

What You'll Learn

  • Distinguishing 500, 502, 503, and 504
  • Structuring server error responses safely
  • Trace IDs for debugging

Why It Matters

Server errors are inevitable. Proper error responses help you debug while preventing information leakage to attackers.

Code Examples

// Safe server error response
{
  "error": "INTERNAL_ERROR",
  "message": "An unexpected error occurred",
  "trace_id": "txn-abc123def456",
  "support_url": "https://status.example.com"
}

// Service unavailable
{
  "error": "SERVICE_UNAVAILABLE",
  "message": "Service is temporarily unavailable",
  "retry_after_seconds": 60,
  "maintenance_url": "https://status.example.com"
}
# Server error handler with trace ID
import uuid

@app.errorhandler(500)
def handle_server_error(error):
    trace_id = str(uuid.uuid4())
    # Log the full error internally
    app.logger.error(f"Server error {trace_id}: {error}")

    return jsonify({
        "error": "INTERNAL_ERROR",
        "message": "An unexpected error occurred",
        "trace_id": trace_id
    }), 500
// Express server error handler
app.use((err, req, res, next) => {
  const traceId = uuidv4();
  console.error(`[${traceId}]`, err);

  res.status(err.status || 500).json({
    error: 'INTERNAL_ERROR',
    message: err.status === 503
      ? 'Service temporarily unavailable'
      : 'An unexpected error occurred',
    trace_id: traceId
  });
});

Common Mistakes

1. Exposing Stack Traces to Clients

Stack traces reveal implementation details that aid attackers.

2. No Trace IDs

Without trace IDs, you can't correlate a bug report with your logs.

3. Returning 500 for Timeouts

Use 504 Gateway Timeout for upstream timeouts, not 500.

4. No Health Check Endpoint

Provide a /health endpoint so clients can check service status.

5. Not Differentiating 502 vs 503

502 = upstream server bad; 503 = this server overloaded/down.

Practice Questions

  1. What is the difference between 502 and 503?
  2. Why should stack traces be hidden in production?
  3. What is a trace ID and why is it important?
  4. What status code indicates a gateway timeout?
  5. How should maintenance periods be communicated?

Answers:

  1. 502 = upstream server returned a bad response; 503 = this server unavailable.
  2. Stack traces reveal file paths, library versions, and internal logic.
  3. A unique identifier for the request that helps correlate client reports with server logs.
  4. 504 Gateway Timeout.
  5. Return 503 with a Retry-After header and link to a status page.

Challenge: Design a server error handling system that includes trace IDs, logs the full error internally, returns safe messages externally, and supports maintenance mode with 503.

FAQ

Should I return 500 for database connection failures?

: Yes. The server can't function without the database.

Can I return a 5xx error with a custom body?

: Yes. Standard status codes with structured JSON bodies.

What status code for a partially failed operation?

: 200 with partial results or 207 Multi-Status for batch operations.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro