...
Issue Status as of Jul 13, 2017 ISSUE DESCRIPTION AND IMPACT SERVER-28323 added strict checks on conversions between Javascript strings and functions. After upgrading to MongoDB 3.4.6, 3.2.14, or 3.2.15 users may encounter the following error message when using mapReduce: 2017-07-10T16:53:32.121-0400 E QUERY [thread1] Error: map reduce failed:{ "ok" : 0, "errmsg" : "SyntaxError: missing ) in parenthetical @:1:118\n", "code" : 139, "codeName" : "JSInterpreterFailure" } : AFFECTED VERSIONS MongoDB 3.2.14, 3.2.15, and 3.4.6. ISSUE STATUS This ticket tracks work to relax some of these constraints in future versions of MongoDB and provide a more user-friendly error message. DIAGNOSIS AND WORKAROUNDS Users encountering this error should examine the inputs to the mapReduce command and ensure they are functions. As an example, consider the following mapReduce command, which runs on 3.4.5: > var mapFunction1 = "function() {emit(this.cust_id, this.price);};" > var reduceFunction1 = "function(keyCustId, valuesPrices) {return Array.sum(valuesPrices);};" > db.orders.insert({ cust_id: "abc123", ord_date: new Date("Oct 04, 2012"), status: 'A', price: 25, items: [ { sku: "mmm", qty: 5, price: 2.5 }, { sku: "nnn", qty: 5, price: 2.5 } ] }) WriteResult({ "nInserted" : 1 }) > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) { "result" : "map_reduce_example", "timeMillis" : 226, "counts" : { "input" : 2, "emit" : 2, "reduce" : 1, "output" : 1 }, "ok" : 1 } Running the same map-reduce command against 3.4.6 results in: > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) 2017-07-10T16:53:31.933-0400 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed 2017-07-10T16:53:31.934-0400 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok 2017-07-10T16:53:32.121-0400 E QUERY [thread1] Error: map reduce failed:{ "ok" : 0, "errmsg" : "SyntaxError: missing ) in parenthetical @:1:118\n", "code" : 139, "codeName" : "JSInterpreterFailure" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DBCollection.prototype.mapReduce@src/mongo/shell/collection.js:1352:1 @(shell):1:1 The error message appears because the mapReduce functions are strings, not functions. Fixing the types of the mapReduce functions resolves the error: > var reduceFunction1 = function(keyCustId, valuesPrices) {return Array.sum(valuesPrices);}; > var mapFunction1 = function() {emit(this.cust_id, this.price);}; > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) { "result" : "map_reduce_example", "timeMillis" : 247, "counts" : { "input" : 2, "emit" : 2, "reduce" : 1, "output" : 1 }, "ok" : 1 } Users should consider using native Javascript objects in their application code if the driver supports them. Original Summary MapReduce failure with 3.4.6 Original Description When performing a mapreduce that works on all previous versions including 3.4.5, we are now receiving the error "missing ) in parenthetical map reduce @15:17". A rollback to 3.4.5 from 3.4.6 was required to resolve this.
shane.harvey commented on Thu, 20 Jul 2017 17:26:53 +0000: egriffiths1A - Wrapping the function with a bson.Code object does not work around this issue. Whether a string or bson.Code, the JavaScript code still needs to be a valid function definition according to the server. For example, adding a trailing semi-colon results in the same "SyntaxError: missing ) in parenthetical @:1:45" error: >>> from pymongo import MongoClient >>> from bson.code import Code >>> db = MongoClient().aggregation_example >>> db.orders.insert_one({ "cust_id": "abc123", "price": 25}) ObjectId('5970e49d947616f9815ceb98') >>> map_str = "function() {emit(this.cust_id, this.price);}" >>> reduce_str = "function(id, prices) {return Array.sum(prices);}" >>> db.orders.map_reduce(map_str, reduce_str, {"inline":1}) {u'counts': {u'input': 1, u'reduce': 0, u'emit': 1, u'output': 1}, u'timeMillis': 15, u'ok': 1.0, u'results': [{u'_id': u'abc123', u'value': 25.0}]} >>> db.orders.map_reduce(map_str+';', reduce_str+';', {"inline":1}) Traceback (most recent call last): File "", line 1, in File "pymongo/collection.py", line 2090, in map_reduce collation=collation) File "pymongo/collection.py", line 232, in _command collation=collation) File "pymongo/pool.py", line 440, in command collation=collation) File "pymongo/network.py", line 116, in command parse_write_concern_error=parse_write_concern_error) File "pymongo/helpers.py", line 210, in _check_command_response raise OperationFailure(msg % errmsg, code, response) pymongo.errors.OperationFailure: SyntaxError: missing ) in parenthetical @:1:45 >>> db.orders.map_reduce(Code(map_str+';'), Code(reduce_str+';'), {"inline":1}) Traceback (most recent call last): File "", line 1, in File "pymongo/collection.py", line 2090, in map_reduce collation=collation) File "pymongo/collection.py", line 232, in _command collation=collation) File "pymongo/pool.py", line 440, in command collation=collation) File "pymongo/network.py", line 116, in command parse_write_concern_error=parse_write_concern_error) File "pymongo/helpers.py", line 210, in _check_command_response raise OperationFailure(msg % errmsg, code, response) pymongo.errors.OperationFailure: SyntaxError: missing ) in parenthetical @:1:45 egriffiths1a commented on Thu, 20 Jul 2017 11:27:09 +0000: Is there any work around when using PyMongo and define the functions inside a Code object from bson.code like: reducer = Code(""" function(key, values) { ... } """) then use it as the reducer argument of PyMongo's map_reduce. Same for mapper and finalizer. Thanks and best regards, Edouard. ramon.fernandez commented on Tue, 11 Jul 2017 00:01:42 +0000: Thanks for the reproducer oleg@evergage.com; we're discussing whether there's something mongod can do in terms of relaxing these constraints or at least provide a more useful error message. Regards, Ramón. oleg@evergage.com commented on Mon, 10 Jul 2017 21:22:50 +0000: I have confirmed that removing an extra ";" in a failing instance of MapReduce made it work with 3.4.6 again. So I would recommend downgrading the severity of this bug at this point, to perhaps simply major? (Since it can be worked around with simple enough client updates). spencer.jackson@10gen.com commented on Mon, 10 Jul 2017 21:08:19 +0000: SERVER-28323 made the server and shell more strict about conversions between strings and functions. I have made a small example which triggers this error message. The following runs on 3.4.5: MongoDB Enterprise > var mapFunction1 = "function() { emit(this.cust_id, this.price); };" MongoDB Enterprise > var reduceFunction1 = "function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); };" MongoDB Enterprise > db.orders.insert({ cust_id: "abc123", ord_date: new Date("Oct 04, 2012"), status: 'A', price: 25, items: [ { sku: "mmm", qty: 5, price: 2.5 }, { sku: "nnn", qty: 5, price: 2.5 } ] }) WriteResult({ "nInserted" : 1 }) MongoDB Enterprise > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) { "result" : "map_reduce_example", "timeMillis" : 226, "counts" : { "input" : 2, "emit" : 2, "reduce" : 1, "output" : 1 }, "ok" : 1 } Running it against 3.4.6 results in: MongoDB Enterprise > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) 2017-07-10T16:53:31.933-0400 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed 2017-07-10T16:53:31.934-0400 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok 2017-07-10T16:53:32.121-0400 E QUERY [thread1] Error: map reduce failed:{ "ok" : 0, "errmsg" : "SyntaxError: missing ) in parenthetical @:1:118\n", "code" : 139, "codeName" : "JSInterpreterFailure" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DBCollection.prototype.mapReduce@src/mongo/shell/collection.js:1352:1 @(shell):1:1 It's complaining because the map/reduce functions are strings, not functions. Admittedly, the error message is not clear. Fixing the types resolves the error. MongoDB Enterprise > var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; MongoDB Enterprise > var mapFunction1 = function() { emit(this.cust_id, this.price); }; MongoDB Enterprise > db.orders.mapReduce(mapFunction1, reduceFunction1, { out: "map_reduce_example" }) { "result" : "map_reduce_example", "timeMillis" : 247, "counts" : { "input" : 2, "emit" : 2, "reduce" : 1, "output" : 1 }, "ok" : 1 } Take a look at your inputs to map reduce, and ensure they are functions. oleg@evergage.com commented on Mon, 10 Jul 2017 21:06:06 +0000: Attached is a reproducible test case written using Java driver 3.3.0 and Maven. It appears to be that the problem is due to the "reduce" function having an extra semicolon after the function() {} definition. When I comment out line Server30009Test.java:32 in the attachment, the test passes with MongoDB 3.4.6. It fails with the semicolon on 3.4.6, but passes with it on 3.4.4. ips commented on Sat, 8 Jul 2017 22:01:55 +0000: The only issue I see in the 3.4.6 change log that mentions JavaScript or map-reduce is: https://jira.mongodb.org/browse/SERVER-28323 (Don’t pass JavaScript scopes a function ID number) Could that by any chance be the cause of the regression? ips commented on Sat, 8 Jul 2017 21:52:05 +0000: We are seeing this as well after upgrading to 3.4.6. mokeefe commented on Fri, 7 Jul 2017 16:01:40 +0000: We are currently running into the same error on our system. MapReduce tasks which worked on all previous versions, including 3.4.5, are now failing with the same error message: Unable to find source-code formatter for language: shell. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml SyntaxError: missing ) in parenthetical @:653:700:01:01 I'm working on finding a minimal map-reduce command which reproduces this; I'll post it once I have one. thomas.schubert commented on Thu, 6 Jul 2017 15:55:07 +0000: Hi bcalev, Thanks for reporting this issue. Would you please provide the problematic map reduce command, so we can reproduce and investigate the issue? Kind regards, Thomas