Skip to content

Stats.hasErrors() ignores the processErrors hook (asymmetric with hasWarnings()) #22279

Closed

Description

@Eshiv-Pandey

Have you used AI?

Yes

Which part of webpack is affected?

not sure

Bug Description

Stats.hasErrors() reads compilation.errors directly, while its sibling Stats.hasWarnings() reads through compilation.getWarnings() — i.e. through the processWarnings waterfall hook. As a result, a plugin that filters entries out of the processErrors hook is contradicted by hasErrors(): stats.toJson().errors is empty, yet stats.hasErrors() still returns true.

Relevant code (lib/stats/Stats.js, lib/Stats.js in released 5.x):

hasWarnings() {
    return (
        this.compilation.getWarnings().length > 0 ||   // via processWarnings hook
        this.compilation.children.some((child) => child.getStats().hasWarnings())
    );
}

hasErrors() {
    return (
        this.compilation.errors.length > 0 ||          // reads the array directly — asymmetric
        this.compilation.children.some((child) => child.getStats().hasErrors())
    );
}

getErrors() calls this.hooks.processErrors.call(this.errors), so hasErrors() bypasses any tap that a plugin registered to filter/suppress errors.

Link to Minimal Reproduction and steps to reproduce

Reproducible with a tiny plugin that empties processErrors:

const webpack = require("webpack");

const compiler = webpack({
    entry: "./missing", // produces a module-not-found error
    plugins: [
        {
            apply(compiler) {
                compiler.hooks.compilation.tap("Repro", (compilation) => {
                    compilation.hooks.processErrors.tap("Repro", () => []);
                });
            }
        }
    ]
});

compiler.run((err, stats) => {
    console.log("errors:", stats.toJson({ errorDetails: false }).errors.length); // 0
    console.log("hasErrors:", stats.hasErrors());                                 // true (bug)
});

Steps:

  1. Tap compilation.hooks.processErrors to return [].
  2. Compile something that errors.
  3. stats.toJson().errors is empty, but stats.hasErrors() is true.

Expected Behavior

hasErrors() should reflect the same error list that toJson() and getErrors() expose — i.e. respect the processErrors hook, mirroring hasWarnings()/processWarnings. With the errors filtered out, hasErrors() should return false.

Actual Behavior

hasErrors() returns true even though the processErrors hook has removed every error and toJson().errors is empty.

Environment

webpack: 5.111.1 (also present on current main)
Node: 20.20.0
OS: Windows 11

Is this a regression?

No

Last Working Version

Additional Context

hasWarnings() was already routed through getWarnings(); hasErrors() was simply never updated to match. Fix: route hasErrors() through getErrors(). A PR follows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions