Skip to content

[duplicate-code] Duplicate Code Pattern: HTTP Error Response Format Inconsistency #2828

@github-actions

Description

@github-actions

Part of duplicate code analysis: #2825

Summary

The server package sends HTTP error responses in two incompatible formats depending on the code path. internal/server/auth.go uses http.Error() which emits a text/plain body, while internal/server/handlers.go uses writeJSONResponse() which emits application/json. Clients (including MCP SDK clients) that parse error bodies as JSON will receive an unparseable plain-text body when an auth error occurs.

Duplication Details

Pattern: Mixed HTTP error response formats

  • Severity: Medium
  • Occurrences: 4+ response-writing call-sites across 2 files
  • Locations:
    • internal/server/auth.go ~line 51 — http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized)
    • internal/server/auth.go ~line 59 — http.Error(w, "Unauthorized: invalid API key", http.StatusUnauthorized)
    • internal/server/handlers.go ~line 51 — writeJSONResponse(w, http.StatusGone, map[string]interface{}{...})
    • internal/server/handlers.go ~line 63 — writeJSONResponse(w, http.StatusOK, map[string]interface{}{...})

Variant 1 — plain text (auth.go):

http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized)
// Content-Type: text/plain; charset=utf-8
// Body: Unauthorized: missing Authorization header\n

Variant 2 — JSON (handlers.go):

writeJSONResponse(w, http.StatusGone, map[string]interface{}{
    "error": "server_not_found",
    "message": "...",
})
// Content-Type: application/json
// Body: {"error":"server_not_found","message":"..."}

Impact Analysis

  • Maintainability: Developers adding new error paths must know which format to use — there's no enforced convention.
  • Bug Risk: Medium — JSON-parsing clients that inspect 401 responses will fail to parse the body and may produce confusing error messages.
  • API Consistency: The MCP Gateway spec implies a JSON API; mixing text/plain for auth errors is inconsistent with the rest of the API surface.

Refactoring Recommendations

  1. Standardise on writeJSONResponse for all HTTP error paths in the server package:

    // Replace in auth.go:
    // Before:
    http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized)
    // After:
    writeJSONResponse(w, http.StatusUnauthorized, map[string]string{
        "error":   "unauthorized",
        "message": "missing Authorization header",
    })
  2. Consider a dedicated writeErrorResponse helper to enforce the structure across all error paths:

    // writeErrorResponse writes a JSON error response with a consistent shape.
    func writeErrorResponse(w http.ResponseWriter, statusCode int, code, message string) {
        writeJSONResponse(w, statusCode, map[string]string{
            "error":   code,
            "message": message,
        })
    }
  3. Estimated effort: < 30 minutes; risk: very low (format change only, existing tests may need body-assertion updates).

Implementation Checklist

  • Replace http.Error calls in auth.go with writeJSONResponse (or writeErrorResponse)
  • Add writeErrorResponse helper to http_helpers.go if adopting it
  • Update any tests that assert on plain-text 401 bodies
  • Verify no other files in internal/server/ use http.Error
  • Confirm Content-Type: application/json on all non-2xx responses

Parent Issue

See parent analysis report: #2825
Related to #2825

Generated by Duplicate Code Detector ·

  • expires on Apr 6, 2026, 6:10 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions