oxc-project/oxc · error

Unexpected return statement in constructor.

Error message

Unexpected return statement in constructor.

What it means

Diagnostic from the oxlint rule `no-constructor-return` (crates/oxc_linter/src/rules/eslint/no_constructor_return.rs). It fires on a `return` statement carrying a value inside a class MethodDefinition whose kind is `constructor`. Constructor return values are discarded when invoked with `new` (unless returning an object, which replaces `this` — a niche source of bugs), so returning a value signals confusion about constructor semantics.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_constructor_return.rs:13

use oxc_ast::{
    AstKind,
    ast::{MethodDefinition, MethodDefinitionKind},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::Span;

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

fn no_constructor_return_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected return statement in constructor.")
        .with_help("Remove the return statement from the constructor. If you need early exit, use a bare `return;` with no value.")
        .with_label(span)
}

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

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow returning a value from a constructor.
    ///
    /// ### Why is this bad?
    ///
    /// In JavaScript, returning a value in the constructor of a class may be a mistake.
    /// Forbidding this pattern prevents mistakes resulting from unfamiliarity with the language or a copy-paste error.
    ///
    /// ### Examples

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Remove the return statement so construction always yields `this`.
  2. For early exit, use a bare `return;` (no value) as the help text suggests, or throw on invalid input.
  3. If callers need a value or null on failure, convert to a factory function or static method (`Foo.create()` returning `new Foo()` or null).
  4. Never rely on returning a different object from a constructor unless that substitution is the documented design.

Example fix

// before
class Connection {
  constructor(cfg) {
    if (!cfg.url) return null;
  }
}

// after
class Connection {
  constructor(cfg) {
    if (!cfg.url) throw new Error('url required');
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Gate: `return <value>;` inside a constructor (heuristic on class bodies)
const ctorReturn = /constructor\s*\([^)]*\)\s*\{[^}]*\breturn\s+[^;\s]/.test(src);

Prevention

When it happens

Trigger: A ReturnStatement with a non-null `argument` lexically inside a MethodDefinition with `kind == Constructor` — e.g. `class A { constructor() { return this.value; } }` or `constructor(x) { if (!x) return null; }`.

Common situations: Factory-ish classes converted from functions that returned values; early-exit validation written as `return null` in constructors; code moved between `function Foo()` and `class Foo` during modernization where the old return became meaningless or silently changes behavior when it returns an object.

Related errors


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