70

When deploying my Rails app I get the following error:

rake aborted!
   ExecJS::ProgramError: Unexpected token punc «(», expected punc «:» (line: 15, col: 14, pos: 265)

   Error
   at new JS_Parse_Error (/tmp/execjs20150524-4411-1p45n63js:2359:10623)
   at js_error (/tmp/execjs20150524-4411-1p45n63js:2359:10842)
   at croak (/tmp/execjs20150524-4411-1p45n63js:2359:19086)
   at token_error (/tmp/execjs20150524-4411-1p45n63js:2359:19223)
   at expect_token (/tmp/execjs20150524-4411-1p45n63js:2359:19446)
   at expect (/tmp/execjs20150524-4411-1p45n63js:2359:19584)
   at /tmp/execjs20150524-4411-1p45n63js:2359:28513
   at /tmp/execjs20150524-4411-1p45n63js:2359:19957
   at expr_atom (/tmp/execjs20150524-4411-1p45n63js:2359:27269)
   at maybe_unary (/tmp/execjs20150524-4411-1p45n63js:2359:30019)new JS_Parse_Error ((execjs):2359:10623)
   js_error ((execjs):2359:10842)
   croak ((execjs):2359:19086)
   token_error ((execjs):2359:19223)
   expect_token ((execjs):2359:19446)
   expect ((execjs):2359:19584)
   (execjs):2359:28513
   (execjs):2359:19957
   expr_atom ((execjs):2359:27269)
   maybe_unary ((execjs):2359:30019)

The file in question is valid, it works on localhost. I also tried running rake assests:precompile on localhost, it all passes. Finally, I tried to remove the content from the file, git push and redeploy - still got the same error. Only completely removing the file and re-deploying helps.

Would appreciate any ideas.

orion3
  • 9,797
  • 14
  • 67
  • 93
  • Are you talking about manifest file? pls explain it clearly – Kamesh May 24 '15 at 10:28
  • No, it's not a manifest file. It's a .js file that is included into application.js with the //= require directive. – orion3 May 24 '15 at 10:52
  • Which CSS code cause this problem? Can you provide it? Which version of execjs are you using? – andreanne.wintheiser May 24 '15 at 12:32
  • It's not CSS code, it's Javascript. Unfortunately I can't provide it, but it is valid and compiles just fine with `rake asset:precompile" on localhost. Not sure how to check ExecJS version, my Gemfile.lock has execjs, but lists no version. – orion3 May 24 '15 at 14:35
  • Apologies, execjs version in my Gemfile.lock is 2.5.2. – orion3 May 24 '15 at 16:25
  • http://stackoverflow.com/questions/12574977/rake-assetsprecompile-gives-punc-error?rq=1 Check here – Kamesh May 24 '15 at 17:55
  • Nope, this doesn't help. I've seen this post. My Javascript is fine, no errors and works perfectly fine on localhost. – orion3 May 24 '15 at 19:32
  • **Was this ever resolved?** I seem to be having the same problem. Info: sprockets (2.12.3), uglifier (2.2.1), execjs (2.5.2), sprockets-rails (2.3.1) – Jeremy Blalock Jun 09 '15 at 06:21
  • I just removed the `uglifier` gem temporarily, but no, it was never resolved. – orion3 Jun 10 '15 at 06:59
  • Exact same error here and removing the `uglifier` gem does allow it compile assets on heroku. – tehfailsafe Jul 01 '15 at 17:44
  • Inspired by your comments, I have just posted an answer to a similar question http://stackoverflow.com/a/32280270/226255 – Abdo Aug 28 '15 at 21:51
  • 2
    Can someone explain how you know what file the error is referring to? Based on this error, how can I determine which is the actual JS file causing the error? – flyingL123 Dec 29 '15 at 23:18
  • 1
    @snitko it would be great for everyone if you select the correct answer, it seems that Rasovan Skendzic 's answer is the best! – Miguel Peniche Jun 12 '17 at 03:39

11 Answers11

260

Here I found help for the same problem you had.

Run rails console and:

JS_PATH = "app/assets/javascripts/**/*.js"; 
Dir[JS_PATH].each do |file_name|
  puts "\n#{file_name}"
  puts Uglifier.compile(File.read(file_name), harmony: true)
end

It will show you the file and the line where the Uglifier is making the problem.

Jason Swett
  • 43,526
  • 67
  • 220
  • 351
Radovan Skendzic
  • 2,923
  • 1
  • 14
  • 22
  • 1
    Why not just `uglify().on("error", function(error){console.log(error);})`? This will give you all you need... – Cipi Aug 22 '16 at 15:22
  • 3
    This is the correct answer. It will find any errors you have regardless if they are the similar to the one above or not. – creativereason Oct 25 '16 at 23:03
  • @Cipi where can i run that? – Harsha M V Nov 24 '16 at 07:23
  • 5
    works! although I just needed to do: `require 'uglifier'` before that – Peter P. Nov 29 '16 at 16:40
  • 2
    Just to add support for erb files with a "*" at the end of dir mask, this may save time to someone: `"app/assets/javascripts/**/*.js*" <-- * at the end – Albert Català Jan 17 '17 at 18:58
  • 1
    Works perfectly. Brilliant! – coryetzkorn Jan 19 '17 at 04:33
  • Hi @cipi. I'm not sure where to add `uglify().on("error", function(error){console.log(error);})`. Can you add more context please? – Robert Reiz Jan 19 '17 at 16:32
  • @Jaswinder I'm sorry you didn't manage to solve your problem with this solution. – Radovan Skendzic Aug 05 '17 at 14:53
  • @RadovanSkendzic Sorry But your solution help me in a different way.Nice solution – Jaswinder Aug 05 '17 at 14:56
  • 1
    I've came back to this multiple times now and it was a huge help. In this case, I got used to writing ES6 and Typescript syntax and some methods were short-hand and using string templates. Isolating it down to the troubled file is a major win. – BradGreens Nov 07 '17 at 20:00
  • 1
    This works great! I had to do a slight syntax change. JS_PATH = "app/assets/javascripts/**/*.js"; Dir[JS_PATH].each do |file_name| puts "\n#{file_name}"; puts Uglifier.compile(File.read(file_name)) end – helloJello Nov 11 '17 at 18:10
  • 1
    for me the error appeared only on precompiled assets on development where no uglifying id done. so for me run that over: `JS_PATH = "public/assets/**/*.js"; – Ondřej Želazko Mar 16 '18 at 15:15
  • You can easily turn this into a rake task, for example `rake javascript:test_compilation` – armchairdj May 08 '18 at 19:46
  • 2
    In my case, it wasn't a specific line that was throwing an error, but the fact that I was using ES6 syntax that was blowing everything up. It may be worth mentioning the need to update uglifier if it doesn't actually give you a specific line as a problem. Once I updated the uglifier, it gave me a useful error about needing to use harmony: true to proceed. – RonLugge Mar 04 '19 at 02:20
  • 1
    For anyone unable to identify the EXACT line causing the issue in the file(s) shown via Radovan's solution, try https://www.jslint.com/ and https://eslint.org/demo/. I first cleaned up my code using the former, and finally identified the issue causing `RAILS_ENV=production rake assets:precompile` to break via the latter. – CFitz Mar 22 '19 at 02:37
  • 1
    @RonLugge Thank you very much! updating uglifier fix my problem too! – Taufiq Muhammadi Jun 29 '19 at 11:56
  • Isn't working for me as it returns "(Unexpected token: operator (<))" on my js.erb files because of the mixed ruby code. – Tristin Jun 04 '22 at 20:18
  • 1
    Updating Uglifier and precompiling my assets did, however, point out the issue. – Tristin Jun 04 '22 at 20:38
33

I suspect, in that js file, you have something like the following:

var User = {
    getName() {
        alert("my name");
    }
}

Replacing it with the right format,

var User = {
    getName: function() {
        alert("my name");
    }
}

worked for me.

Error is clearly saying, it's expecting ":" but it found "(".

MadCoder
  • 641
  • 6
  • 16
  • This was the issue for me. As well as having arrays that use a variable the same name as a key: *Don't use* `{ id, content }` *Do use* `{ id: id, content: content }` – TJ Biddle Jun 07 '16 at 09:06
  • 2
    My issue was default params in a function: `function test(param1='val1', param2='val1') {}`. Apparently that only became a thing in ES2015. – Constant Meiring Feb 12 '17 at 17:54
  • This error is shockingly common when you are context-switching between ES6 and old-school JavaScript! – armchairdj May 08 '18 at 19:40
7

Just encounter the same issue.

My case is someone used syntax that's only support since ES2015, ex

function someThing(param = true) {
    // do something here
};

while this is not supported in our environment.

And the error messages is actually generated by Uglifer.

湯凱甯
  • 101
  • 1
  • 2
6

I'm not sure of your build chain, but I got here by pasting the same error message into Google.

That is called 'shorthand properties' in ES2015. I'm using Babel 6 with Gulp and needed to do an npm install babel-plugin-transform-es2015-shorthand-properties --save-dev and add that transform to my babel plugins.

.pipe(babel({
    plugins: [
        'transform-es2015-shorthand-properties'
    ]
}))

https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es2015-shorthand-properties

jamie-wilson
  • 1,925
  • 21
  • 38
6

I could use https://skalman.github.io/UglifyJS-online/ to identify the correct line number where the issue was. Thankfully, at least the correct file which had an issue was pointed out by grunt uglify

Amrudesh
  • 305
  • 4
  • 6
5

If Radovan's answer isn't working for you due to a problem in a library instead of your code, you can try upgrading Uglifier and enabling ES6 compilation.

Gemfile.lock

gem 'uglifier', '~> 4.1'

config/environments/production.rb

config.assets.js_compressor = Uglifier.new(harmony: true)
sma
  • 407
  • 4
  • 6
5

December/2019 answer: starting on version 4.2.0 (released in Sept/2019), Uglifier now shows a beautiful (colored!) debug output showing you the offending line of code.

I was having a Uglifier::Error: Unexpected character ''` error and I couldn't find it even following all the other solutions in this page.

So go to your Gemfile, and set your Uglifier to be at least 4.2:

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 4.2'

Run bundle update uglifier to update it.

And then just look at the output, it will show you something like this:

enter image description here

sandre89
  • 5,218
  • 2
  • 43
  • 64
3

In my case problem with function definition like,

function someFunctionName(param1, param2=defaultValue){
  //code 
}

Due to above function definition I was getting error, as it is not supported by Uglifier. Default parameters is ES6/ES2015 language specification.

For solution to above problem you can refer Set a default parameter value for a JavaScript function

ShilpeshAgre
  • 291
  • 2
  • 9
1

As the backtrace doesn't provide information about the corrupted file, for me the best way to identify the error is use git bisect.

It allows you to find the commit that introduces a bug.

Let's suppose you are on master, first you start git bisect:

$ git bisect start
$ git bisect bad 

Then you go back to a previous, working revision, let's suppose 20 revision ago.

$ git checkout HEAD~20

You run the same command

$ RAILS_ENV=production rake assets:precompile

If it works you mark revision as good:

$ git bisect good.

git will jump to another revision, you run same command again (assets:precompile) and bassed on the output mark it as good / bad.

In less than 1 minute you should be able to find what's the commit that introduced the issue.

Arnold Roa
  • 7,335
  • 5
  • 50
  • 69
1

Update uglifier gem to last version and update your production.rb

config.assets.js_compressor = Uglifier.new(harmony: true)
Abel
  • 3,989
  • 32
  • 31
0

If you are maintaining a legacy project(with ruby very old version e.g. 1.9.3 and Rails 3.2.x), I suggest you don't use uglifier&exec-js, simply comment out this line of code from config/environments/production.rb:

config.assets.compress = true

also make sure you installed nodejs as the js run time.

refer to: "rake assets:precompile" gives punc error

Siwei
  • 19,858
  • 7
  • 75
  • 95