Skip to content

createExpressError overwrites err.code switch values unconditionally #256

@thehabes

Description

@thehabes

Summary

In controllers/utils.js, the createExpressError() function has a logic error where the switch (err.code) block (lines 104–115) sets error.statusCode and error.statusMessage, but lines 116–117 immediately overwrite both values unconditionally.

Example

When called with { code: 11000 } (duplicate slug/id conflict):

function createExpressError(err) {
    let error = {}
    if (err.code) {
        switch (err.code) {
            case 11000:
                error.statusMessage = `The id provided already exists.  Please use a different _id or Slug.`
                error.statusCode = 409  // ← sets 409
                break
            default:
                error.statusMessage = "There was a mongo error that prevented this request from completing successfully."
                error.statusCode = 500
        }
    }
    error.statusCode = err.statusCode ?? err.status ?? 500      // ← overwrites to 500 (err.statusCode and err.status are undefined)
    error.statusMessage = err.statusMessage ?? err.message ?? "Detected Error"  // ← overwrites to "Detected Error"
    return error
}

The switch correctly sets statusCode = 409 and a descriptive message, but lines 116–117 unconditionally overwrite both. Since the input object { code: 11000 } has no statusCode, status, statusMessage, or message properties, the final result is { statusCode: 500, statusMessage: "Detected Error" }.

Impact

Slug/id conflict errors may be returning 500 Internal Server Error instead of 409 Conflict in production.

Suggested Fix

Only apply the fallback defaults when the switch didn't already set values:

function createExpressError(err) {
    let error = {}
    if (err.code) {
        switch (err.code) {
            case 11000:
                error.statusMessage = `The id provided already exists.  Please use a different _id or Slug.`
                error.statusCode = 409
                break
            default:
                error.statusMessage = "There was a mongo error that prevented this request from completing successfully."
                error.statusCode = 500
        }
    }
    error.statusCode = error.statusCode ?? err.statusCode ?? err.status ?? 500
    error.statusMessage = error.statusMessage ?? err.statusMessage ?? err.message ?? "Detected Error"
    return error
}

The key change is checking error.statusCode and error.statusMessage first (values set by the switch), before falling back to err properties.

Found During

Code review of PR #255 (Content-Type validation). This bug is pre-existing and unrelated to that PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions