metaskills / less-rails

:-1: :train: Less.js For Rails

Home Page:http://github.com/metaskills/less-rails

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ArgumentError - invalid byte sequence in UTF-8

mvastola opened this issue · comments

I'm getting the following error when rails is attempting to precompile a stylesheet.

ArgumentError - invalid byte sequence in UTF-8:
  less-rails (2.7.1) lib/less/rails/import_processor.rb:23:in `depend_on'
  less-rails (2.7.1) lib/less/rails/import_processor.rb:27:in `block in depend_on'
  less-rails (2.7.1) lib/less/rails/import_processor.rb:24:in `depend_on'
  less-rails (2.7.1) lib/less/rails/import_processor.rb:27:in `block in depend_on'
  less-rails (2.7.1) lib/less/rails/import_processor.rb:24:in `depend_on'
  less-rails (2.7.1) lib/less/rails/import_processor.rb:18:in `evaluate'
  tilt (2.0.2) lib/tilt/template.rb:99:in `render'
  sprockets (3.5.2) lib/sprockets/legacy_tilt_processor.rb:25:in `call'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:75:in `call_processor'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:57:in `block in call_processors'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:56:in `call_processors'
  sprockets (3.5.2) lib/sprockets/loader.rb:134:in `load_from_unloaded'
  sprockets (3.5.2) lib/sprockets/loader.rb:60:in `block in load'
  sprockets (3.5.2) lib/sprockets/loader.rb:318:in `fetch_asset_from_dependency_cache'
  sprockets (3.5.2) lib/sprockets/loader.rb:44:in `load'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:20:in `block in initialize'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:47:in `load'
  sprockets (3.5.2) lib/sprockets/bundle.rb:23:in `block in call'
  sprockets (3.5.2) lib/sprockets/utils.rb:183:in `dfs'
  sprockets (3.5.2) lib/sprockets/bundle.rb:24:in `call'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:75:in `call_processor'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:57:in `block in call_processors'
  sprockets (3.5.2) lib/sprockets/processor_utils.rb:56:in `call_processors'
  sprockets (3.5.2) lib/sprockets/loader.rb:134:in `load_from_unloaded'
  sprockets (3.5.2) lib/sprockets/loader.rb:60:in `block in load'
  sprockets (3.5.2) lib/sprockets/loader.rb:318:in `fetch_asset_from_dependency_cache'
  sprockets (3.5.2) lib/sprockets/loader.rb:44:in `load'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:20:in `block in initialize'
  sprockets (3.5.2) lib/sprockets/cached_environment.rb:47:in `load'
  sprockets (3.5.2) lib/sprockets/base.rb:66:in `find_asset'
  sprockets (3.5.2) lib/sprockets/base.rb:73:in `find_all_linked_assets'
  sprockets (3.5.2) lib/sprockets/manifest.rb:134:in `block in find'
  sprockets (3.5.2) lib/sprockets/manifest.rb:133:in `find'
  sprockets-rails (3.0.0) lib/sprockets/railtie.rb:41:in `precompiled_assets'
  sprockets-rails (3.0.0) lib/sprockets/railtie.rb:34:in `asset_precompiled?'
  sprockets-rails (3.0.0) lib/sprockets/railtie.rb:205:in `block (3 levels) in <class:Railtie>'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:346:in `precompiled?'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:350:in `raise_unless_precompiled_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:335:in `find_debug_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:217:in `block in lookup_debug_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:230:in `block in resolve_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:229:in `resolve_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:216:in `lookup_debug_asset'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:129:in `block in javascript_include_tag'
  sprockets-rails (3.0.0) lib/sprockets/rails/helper.rb:128:in `javascript_include_tag'
  app/views/layouts/main_site.html.erb:6:in `_app_views_layouts_main_site_html_erb__3304990932101485186_69970548490080'
[snipped]

Upon further analysis, it seems the issue is that less-rails is resolving a css @import directive to refer to a image asset in my rails app rather than another stylesheet. Obviously, trying to parse a binary image as text/css explains this error.

The including CSS (really an .scss) file in question is innocuous enough. The error is thrown on a line containing:
@import 'theme/responsive'; and the file is located at app/assets/stylesheets/contrib/theme.scss.

In my debugging, I inserted a breakpoint here and evaluated the following code to receive these values:

>> base 
=> "contrib"
>> path 
=> "theme/responsive" 
>> scope.resolve('theme/responsive') 
=> "/home/mvastola/src/partyista_web/app/assets/images/theme/responsive.png" 
>> scope.resolve('theme/responsive.scss') 
=> "/home/mvastola/src/partyista_web/app/assets/stylesheets/theme/responsive.scss"

I'm not too familiar with how this gem works/is supposed to work, but it would seem to me that app/assets/images shouldn't be searched for CSS/SCSS/LESS imports at all.

Note that this issue was solved (once I deciphered the source of the error from the cryptic message) by changing @import 'theme/responsive'; to use a relative path: @import '../theme/responsive';, which perhaps is the better way to go regardless, but that is beside the point that the former should have been supported (or at least returned a more descriptive error).

Note that this error seems to only occur when the version of sprockets >= 3.0.0, but the codebase for sprockets is so vast and unfamiliar to me I really can't narrow down the error any further than that at the moment..

Can you prepare minimal app to reproduce this?

Sure. I'll give it a go.

@simi Here you go. Just clone and bundle exec rails s (and go to the root path).

I've got that. Working on a fix.

Sweet. Thanks!

Can you test this?

gem 'less-rails', github: 'metaskills/less-rails', branch: 'depends_only_on_less_files'

Nope. Doesn't work. My file in question ends in .scss.

Hmm.. not entirely sure if this is on the right track, but check out this. It looks like the #resolve method (which is what PATHNAME_FINDER calls, can optionally take a 2nd argument that can specify the file's mime type.

What if you added a 3rd argument to PATHNAME_FINDER which, if present, became the 2nd arg to scope.resolve, and called it as indicated in the link above to limit it to text/css?

In any case, going on what I do know, I think you should probably go by mime type rather than by extension..

Wait... ignore that last.
It does work. (Not sure how exactly, but that's ok!)
I was just being dumb.

@simi Thanks for your excellent work (and ultra-fast response) on this.
Do you have any idea whenabouts this fix will be merged/released? (I just want to make sure we update our Gemfile appropriately so we resume tracking bug/security fixes as they are released.)

Thanks again!

I'm not actively using less-rails now in my projects, so I'm not sure if this is not breaking anything. Do you think your project is big enough to confirm that? Or do you have any chance to test this fix in some bigger project? It will be nice to also prepare some less-rails test project to ensure it is not breaking things.

Also I'm not sure how big this change is. Do we need patch, minor or major bump?

@metaskills @maxd any ideas?

Well my project is big, but it doesn't use less that much (it uses scss much more). So I'm not sure it'd be the best to go by. That said, the fix works perfectly.

@simi, Idea: as a compromise, could this change be merged but as an "experimental setting" that is off by default?

So, for instance, this new code would only come into use if I ran something like the following (presumably in an initializer):

Less::Rails::ImportProcessor.filter_by_extension = true

I would be perfectly amenable to this (especially on a trial basis while we establish if the code is stable) because my only concern is that I don't want to be fetching code that isn't going to be maintained with bug/security updates.

Also, this way, this fix is easily implementable for anyone else experiencing this issue.

Finally, my 2 cents (for what it's worth): if you go this route, since the change doesn't affect default functionality and won't change anything for users currently using the gem, I'd just bump the revision part of the version.

Testing this out too now. Works so far. Thanks!

hey @simi I've got a 37 kloc less rails project consisting of extensive @imports including one from bower component supplied less file. And I'm actively developing it and will for sure for at least half a year to come. If you can consider this a decent project, I can switch less-rails version for testing and provide feedback. But first we need to merge #116 :) because before that I need my branch to be active :)

Ok, so now feel free to invite me for testing as promised. So what branch are we talking about here? depends_only_on_less_files?

Hey there, what's the state of the depends_only_on_less_files branch? We updated from sprockets 2 to 3, and hit this error. Using the depends_only_on_less_files branch fixed it for us.

this is merged in less-rails?
gem 'less-rails', github: 'metaskills/less-rails', branch: 'depends_only_on_less_files'
worked for me! :D THANKS!!!

+1, seems like using depends_only_on_less_files branch helped also in my case.

Had the same issue, the depends_only_on_less_files branch fixed it for me.

I'm not actively using less-rails now in my projects, so I'm not sure if this is not breaking anything. Do you think your project is big enough to confirm that? Or do you have any chance to test this fix in some bigger project? It will be nice to also prepare some less-rails test project to ensure it is not breaking things.

I only have one .less file in my project, so I'm not sure its not breaking anything either.
Is there anyway we could find out?

ℹ️ no activity for years, closing