Skip to content


Subversion checkout URL

You can clone with
Download ZIP


A fix to make parse errors more visible #19

wants to merge 1 commit into from

5 participants


Right now, a lot of parsing errors are actually silently swallowed. This fixes that. Rather than add a new exception class, I modified the existing ParseError to just pass along the entire original exception - this means anyone actually using the ParseError for anything will have to slightly modify their code.


why say: It is intended to wrap a native V8::JSError, or any other error type thrown from the Less.js?
why not just say: It is intended to wrap any error throw by Less.js?


It seems weird to change the definition of ParseError from being something that mimicked a V8::Error to now be something that just holds a reference to one. Shouldn't there be other changes elsewhere in the code to deal with this switch up?


I have to say I agree with @abloom. I like the fact that the original ParseError had the same backtrace as the original error, this makes detecting where the error actually happened a snap. Is there any reason we can't have one change and not the other?


I mean, I'm stashing away the original exception - you just have to call '.original.backtrace' now instead. The other exceptions that Less.js can generate don't always have backtraces, as such. For example: - creates a new LessError - has what I assume is a backtrace as 'stack', but which I believe would be empty in this case

Basically, I was trying to keep the semantics of rescuing ParseError to catch parsing errors, and not having to special case on a V8 error with the expected properties, vs. something the Less.js parser can return in that callback that behaves differently.


+1 swallowing exceptions is not ideal. This error was raised on less-rails because of it.



this one's a bit obsolete esp. since therubyrhino support - depends on the JS runtime how native exception are visible

@kares kares closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 11 additions and 14 deletions.
  1. +9 −14 lib/less/parser.rb
  2. +2 −0  spec/less/parser_spec.rb
23 lib/less/parser.rb
@@ -56,7 +56,7 @@ def initialize(options = {})
- # Convert `less` source into a abstract syntaxt tree
+ # Convert `less` source into a abstract syntax tree
# @param [String] less the source to parse
# @return [Less::Tree] the parsed tree
def parse(less)
@@ -65,6 +65,7 @@ def parse(less)
@parser.parse(less, lambda {|e, t|
error = e; tree = t
+ raise if error if tree
@@ -90,21 +91,15 @@ def to_css(options = {})
- # Thrown whenever an error occurs parsing
- # and/or serializing less source. It is intended
- # to wrap a native V8::JSError
+ # Thrown whenever an error occurs parsing and/or serializing less source. It is intended
+ # to wrap a native V8::JSError, or any other error type thrown from the Less.js code
+ # itself.
class ParseError < StandardError
+ attr_reader :original
- # Copies over `error`'s message and backtrace
- # @param [V8::JSError] error native error
- def initialize(error)
- super(error.message)
- @backtrace = error.backtrace
- end
- # @return [Array] the backtrace frames
- def backtrace
- @backtrace
+ # @param [Object] error original exception
+ def initialize(original)
+ @original = original
2  spec/less/parser_spec.rb
@@ -14,8 +14,10 @@
subject.parse(".class {width: 1+1}").to_css(:compress => true).strip.should eql ".class{width:2;}"
it "throws a ParseError if the lesscss is bogus" do
expect {subject.parse('{^)')}.should raise_error(Less::ParseError)
+ expect {subject.parse('this surely is invalid@#%@#%@#!!!!')}.should raise_error(Less::ParseError)
describe "when configured with multiple load paths" do
Something went wrong with that request. Please try again.