Skip to content

Errors in mixins are raised at the parent mixin call location rather than the actual line of the error #4559

Open

Description

@uncenter

To reproduce:

Compile the following Less snippet. I used pnpx less foo.less since the browser playground doesn't show line numbers/source ranges for errors.

.my-color-mixin() {
  @result: #000;
}

#my-mixin() {
  background-color: .my-color-mixin();
}

body {
  #my-mixin();
}

Current behavior:

The following error is given:

SyntaxError: Rulesets cannot be evaluated on a property. in /.../foo.less on line 10, column 3:
9 body {
10   #my-mixin();
11 }

This error says that #my-mixin is the erroroneous line, when it is really the line background-color: .my-color-mixin(); within that mixin.

Expected behavior:

The error message should accurately pinpoint the location of the error source instead of the calling mixin. In this case, the mixin being "evaluated on a property" is .my-color-mixin on line 6. This might look something like:

SyntaxError: Rulesets cannot be evaluated on a property. in /.../foo.less on line 6, column ?:
5 #my-mixin() {
6   background-color: .my-color-mixin();
7 }

Environment information:

  • less version: 4.9.1

Another snippet you can try is this:

#my-mixin() {
  // ...
  background-color: .foo();
  // ...
}

body {
  #my-mixin();
}

Again here the compiler will point to the line in body {} rather than the actual line where the undefined .foo() is called.

NameError: .foo is undefined in /.../foo.less on line 8, column 3:
7 body {
8   #my-mixin();
9 }

This issue is especially problematic with longer mixins, where any errors within it is only surfaced at the parent call site which makes it very difficult to track down the actual error.

Activity

  1. dosubot commented on Oct 17, 2026

    @dosubot

    This points to the error rethrow in MixinCall.eval(): it catches errors from evaluating the mixin body and replaces their index and filename with the calling mixin’s location. That explains why both examples end up pointing at #my-mixin(); rather than the failing expression inside it. [1]

    Related PR #4414 preserved more error fields, but still explicitly overwrites index and filename, so that change does not address this location issue. The fix direction would be to preserve the originating location when present and use the call site only as a fallback, similar to the existing error handling in Declaration.eval(). Both snippets here would be useful regression cases. [2] [3]

    To reply, just mention @dosu.


    Docs are dead. Just use Dosu.

    Leave Feedback Ask Dosu about less.js Share Dosu with your team

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions