CartoDB / turbo-carto

CartoCSS preprocessor
BSD 3-Clause "New" or "Revised" License
28 stars 7 forks source link

TypeError: Cannot read property 'replace' of undefined #83

Closed Algunenano closed 5 years ago

Algunenano commented 5 years ago
[2019-05-27 03:42:06.790] [FATAL] [default] - TypeError: Cannot read property 'replace' of undefined
    at columnName (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/helper/column-name.js:4:17)
    at /home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:21:26
    at new Promise (<anonymous>)
    at fn$buckets (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:16:12)
    at LazyFiltersResult.filterGenerator (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:51:37)
    at LazyFiltersResult.get (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/model/lazy-filters-result.js:17:15)
    at LazyFiltersResult.ValuesResult.getLength (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/model/values-result.js:29:15)
    at compatibilityValuesRamp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:191:27)
    at ramp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:147:12)
    at Function.fn$ramp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:65:12)
TypeError: Cannot read property 'replace' of undefined
    at columnName (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/helper/column-name.js:4:17)
    at /home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:21:26
    at new Promise (<anonymous>)
    at fn$buckets (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:16:12)
    at LazyFiltersResult.filterGenerator (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-buckets.js:51:37)
    at LazyFiltersResult.get (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/model/lazy-filters-result.js:17:15)
    at LazyFiltersResult.ValuesResult.getLength (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/model/values-result.js:29:15)
    at compatibilityValuesRamp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:191:27)
    at ramp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:147:12)
    at Function.fn$ramp (/home/ubuntu/www/node-windshaft/releases/20190521103931/node_modules/turbo-carto/src/fn/fn-ramp.js:65:12)
[2019-05-27 03:42:06.790] [INFO] [default] - Process is going to exit with code: 1

This is restarting services in production:

$ grep FATAL node-windshaft.log
[2019-05-27 03:42:06.790] [FATAL] [default] - TypeError: Cannot read property 'replace' of undefined
[2019-05-27 04:00:02.303] [FATAL] [default] - TypeError: Cannot read property 'replace' of undefined
[2019-05-27 05:16:52.777] [FATAL] [default] - TypeError: Cannot read property 'replace' of undefined
$ zgrep "PID=" *.gz
node-windshaft-process.log.6.gz:May 27 05:16:58 api-blue-06 node-windshaft-process: Windshaft tileserver 7.2.0 started on 0.0.0.0:8181 PID=16666 (production)
node-windshaft-process.log.7.gz:May 27 03:43:06 api-blue-06 node-windshaft-process: Windshaft tileserver 7.2.0 started on 0.0.0.0:8181 PID=23557 (production)
node-windshaft-process.log.7.gz:May 27 04:00:21 api-blue-06 node-windshaft-process: Windshaft tileserver 7.2.0 started on 0.0.0.0:8181 PID=29132 (production)

cc/ @CartoDB/rt-managers

rafatower commented 5 years ago

Could reproduce the issue locally with the example in current master and this cartocss:

#populated_places_simple {
  marker-fill-opacity: 1.0;
  marker-line-color: #FFF;
  marker-line-width: 1;
  marker-line-opacity: 1;
  marker-allow-overlap: true;
  marker-width: ramp(, (1,10), quantiles()));
  marker-fill: ramp([pop_max], colorbrewer(YlGnBu), quantiles());
}

note the evil ramp: marker-width: ramp(, (1,10), quantiles()));.

It dies with the following traces (very similar to production one):

``` [2019-06-05 17:12:42.230] [INFO] [default] - undefined OPTIONS development.localhost.lan:8181/api/v1/map 200 0 ms -> text/html; charset=utf-8 ({}) (undefined) [2019-06-05 17:12:42.274] [INFO] [default] - undefined POST development.localhost.lan:8181/api/v1/map 400 43 ms -> application/json; charset=utf-8 ({"anonymous_getMapConfig":39,"overviewsAddedToMapconfig":false,"mapType":"anonymous","total":39}) ({"mainError":{"statusCode":400,"message":"Failed to process marker width property column replace is not a function","name":"Error","type":"layer","subtype":"turbo carto"},"moreErrors":[]}) [2019-06-05 17:12:42.275] [FATAL] [default] - TypeError: Cannot read property 'replace' of undefined at columnName (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/helper/column-name.js:4:17) at /home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:21:26 at new Promise () at fn$buckets (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:16:12) at LazyFiltersResult.filterGenerator (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:51:37) at LazyFiltersResult.get (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/model/lazy-filters-result.js:17:15) at LazyFiltersResult.ValuesResult.getLength (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/model/values-result.js:29:15) at compatibilityValuesRamp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:191:27) at ramp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:147:12) at Function.fn$ramp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:65:12) TypeError: Cannot read property 'replace' of undefined at columnName (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/helper/column-name.js:4:17) at /home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:21:26 at new Promise () at fn$buckets (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:16:12) at LazyFiltersResult.filterGenerator (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-buckets.js:51:37) at LazyFiltersResult.get (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/model/lazy-filters-result.js:17:15) at LazyFiltersResult.ValuesResult.getLength (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/model/values-result.js:29:15) at compatibilityValuesRamp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:191:27) at ramp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:147:12) at Function.fn$ramp (/home/rtorre/src/Windshaft-cartodb/node_modules/turbo-carto/src/fn/fn-ramp.js:65:12) [2019-06-05 17:12:42.277] [INFO] [default] - Process is going to exit with code: 1 [2019-06-05 17:12:42.277] [ERROR] console - (node:26333) [DEP0079] DeprecationWarning: Custom inspection function on Objects via .inspect() is deprecated ```

Note there's a 400 response to a POST with an error message Failed to process marker width property column replace is not a function before dying.

Will work on a fix.

rafatower commented 5 years ago

I wrote a test to reproduce the issue in https://github.com/CartoDB/turbo-carto/pull/84 (all WIP).

It produces the following output:

``` 1) should return an error if it receives an evil ramp (instead of unhandled exception) (node:28736) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'replace' of undefined at columnName (/home/rtorre/src/CartoDB/turbo-carto/src/helper/column-name.js:4:17) at /home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-buckets.js:21:26 at new Promise () at fn$buckets (/home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-buckets.js:16:12) at LazyFiltersResult.filterGenerator (/home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-buckets.js:51:37) at LazyFiltersResult.get (/home/rtorre/src/CartoDB/turbo-carto/src/model/lazy-filters-result.js:17:15) at LazyFiltersResult.ValuesResult.getLength (/home/rtorre/src/CartoDB/turbo-carto/src/model/values-result.js:29:15) at compatibilityValuesRamp (/home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-ramp.js:191:27) at ramp (/home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-ramp.js:147:12) at Function.fn$ramp (/home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-ramp.js:65:12) at /home/rtorre/src/CartoDB/turbo-carto/src/fn/executor.js:32:24 (node:28736) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3) (node:28736) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. (node:28736) UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Failed to process "marker-width" property: column.replace is not a function at /home/rtorre/src/CartoDB/turbo-carto/test/acceptance/regressions.test.js:238:14 at /home/rtorre/src/CartoDB/turbo-carto/src/fn/fn-ramp.js:86:15 (node:28736) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4) ... 1) regressions should return an error if it receives an evil ramp (instead of unhandled exception): Error: Timeout of 500ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/rtorre/src/CartoDB/turbo-carto/test/acceptance/regressions.test.js) ```

When trying to find a suitable fix, I noticed that the the message Failed to process... comes from the exception caught and then relaunched wrapped in a TurboCartoError here:

https://github.com/CartoDB/turbo-carto/blob/08121ef18e2176d96b88cb5f119710c0b8c19488/src/fn/fn-ramp.js#L86

I'd need some help from the Node experts @dgaubert or @oleurud on what's the best way to do error management in this situation. There may well be other cases with similar results (exception caught, relaunched, and then Windshaft dying on them).

rafatower commented 5 years ago

I finally got it fixed in #84

I also tested it end-to-end with the cartocss above and Windshaft-cartodb with this patch:

diff --git a/package.json b/package.json
index aab6a238..36b8e2fe 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "request": "2.87.0",
     "semver": "5.5.0",
     "step-profiler": "0.3.0",
-    "turbo-carto": "0.21.0",
+    "turbo-carto": "github:cartodb/turbo-carto#83-fix-cannot-read-property-replace",
     "underscore": "1.6.0",
     "windshaft": "5.2.1",
     "yargs": "11.1.0"

and instead of dying it does what is meant to do, which is to log the error and carry on:

[2019-06-11 11:25:23.751] [INFO] [default] - undefined POST development.localhost.lan:8181/api/v1/map 400 44 ms -> application/json; charset=utf-8 ({"dbConnSetup":1,"anonymous_getMapConfig":36,"overviewsAddedToMapconfig":false,"mapType":"anonymous","total":37}) ({"mainError":{"statusCode":400,"message":"Failed to process  marker width  property  column replace is not a function","name":"Error","type":"layer","subtype":"turbo carto"},"moreErrors":[]})
rafatower commented 5 years ago

The final fix is in #85

It is released and deployed, working as expected. Cheers!