oxc-project/oxc · warning · OxcDiagnostic

Error message should be a string.

Error message

Error message should be a string.

What it means

Diagnostic from oxlint's `unicorn/error-message` rule. The message argument is an array literal `[...]` or object literal `{...}` — non-string literals that are almost certainly a mistake, since `Error` stringifies them into useless text like the joined array items. The rule checks only these literal forms at the message position of the built-in error constructors; identifiers, calls, and other expressions are not flagged.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/error_message.rs:27

use crate::{AstNode, context::LintContext, rule::Rule, utils::BUILT_IN_ERRORS};

fn missing_message(ctor_name: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Pass a message to the {ctor_name:1} constructor."))
        .with_help(
            "A descriptive message makes the error easier to debug when it is caught or logged.",
        )
        .with_label(span)
}

fn empty_message(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Error message should not be an empty string.")
        .with_help("Provide a non-empty string that describes what went wrong.")
        .with_label(span)
}

fn not_string(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Error message should be a string.")
        .with_help(
            "The first argument to an error constructor should be a string describing the error.",
        )
        .with_label(span)
}

#[derive(Default, Debug, Clone)]
pub struct ErrorMessage;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Enforces providing a `message` when creating built-in `Error` objects to
    /// improve readability and debugging.
    ///
    /// ### Why is this bad?
    ///
    /// Throwing an `Error` without a message, like `throw new Error()`, provides no context

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Join arrays into a single string: `new Error(issues.join(', '))`.
  2. Serialize objects deliberately: `new Error(JSON.stringify(details))`, or keep details on a custom property and pass a summary string as the message.
  3. Subclass Error if you need structured payloads instead of forcing them into the message.

Example fix

// before
throw new Error(['code missing', 'host missing']);
// after
throw new Error('Validation failed: ' + ['code missing', 'host missing'].join(', '));
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: `throw new Error(['code missing', 'host missing'])` or `throw new ValidationError({ field: 'email' })` where the callee is a global built-in error constructor (for user-defined error classes the rule does not fire).

Common situations: Validation code collecting multiple issues and passing the array directly; refactors where an options object was mistakenly put in the message slot.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/a4d13ca2f43f967c. Report an issue: GitHub.