Mustache transform script throwing "Failed to compile inline script" error

Elastic stack: 6.2.2

I am trying to convert the payload to JSON and then pass it to a Webhook action.
My Watcher transform script looks like:

{
  "trigger": {
    "schedule": {
      "interval": "1m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".watcher-history*"
        ],
        "types": [],
        "body": {
          "size": 10,
          "_source": [
            "@timestamp",
            "metadata.name",
            "watch_id"
          ],
          "query": {
            "bool": {
              "filter": [
                {
                  "range": {
                    "@timestamp": {
                      "gte": "now-1m/m"
                    }
                  }
                },
                {
                  "match": {
                    "watch_id": "Watch_1"
                  }
                }
              ]
            }
          },
          "sort": [
            {
              "@timestamp": {
                "order": "asc"
              }
            }
          ]
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gt": 0
      }
    }
  },
  "actions": {
    "watcherWebHook": {
      "transform" : {
        "chain" : [
          {
            "script":  {
              "lang": "mustache",
              "source": "{{#toJson}}ctx.payload.hits.hits{{/toJson}}"
            }
          },
          {
            "script":  {
              "lang": "painless",
              "source": "return [ 'payload': ctx.payload._value.toString() ]"
            }
          }
        ]
      },
      "webhook": {
        "scheme": "http",
        "host": "webhookEndPointServer",
        "port": 80,
        "method": "post",
        "path": "/raise",
        "params": {},
        "body": {
          "source": {
            "payload": {
              "execution_time": "{{ctx.execution_time}}",
              "watch_id": "{{ctx.watch_id}}",
              "body": "{{ctx.payload._value}}"
            }
          },
          "lang": "mustache",
          "options": {
            "content_type": "application/json; charset=UTF-8"
          }
        }
      }
    }
  },
  "throttle_period_in_millis": 1000
}

Whenever I try to save/simulate the watch, ES throws following error:

[WARN ][r.suppressed             ] path: /_xpack/watcher/watch/_execute, params: {}
org.elasticsearch.script.GeneralScriptException: Failed to compile inline script [{{#toJson}}ctx.payload.hits.hits{{/toJson}}] using lang [mustache]
        at org.elasticsearch.script.ScriptService.compile(ScriptService.java:340) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.xpack.watcher.transform.script.ExecutableScriptTransform.<init>(ExecutableScriptTransform.java:47) ~[?:?]
        at org.elasticsearch.xpack.watcher.transform.script.ScriptTransformFactory.createExecutable(ScriptTransformFactory.java:49) ~[?:?]
        at org.elasticsearch.xpack.watcher.transform.script.ScriptTransformFactory.createExecutable(ScriptTransformFactory.java:28) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.transform.chain.ChainTransformFactory.createExecutable(ChainTransformFactory.java:55) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.transform.chain.ChainTransformFactory.createExecutable(ChainTransformFactory.java:31) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.transform.TransformFactory.parseExecutable(TransformFactory.java:53) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.transform.TransformRegistry.parse(TransformRegistry.java:64) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.transform.TransformRegistry.parse(TransformRegistry.java:53) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.actions.ActionWrapper.parse(ActionWrapper.java:224) ~[?:?]
        at org.elasticsearch.xpack.core.watcher.actions.ActionRegistry.parseActions(ActionRegistry.java:73) ~[?:?]
        at org.elasticsearch.xpack.watcher.watch.WatchParser.parse(WatchParser.java:171) ~[?:?]
        at org.elasticsearch.xpack.watcher.watch.WatchParser.parse(WatchParser.java:123) ~[?:?]
        at org.elasticsearch.xpack.watcher.watch.WatchParser.parse(WatchParser.java:88) ~[?:?]
        at org.elasticsearch.xpack.watcher.transport.actions.execute.TransportExecuteWatchAction.masterOperation(TransportExecuteWatchAction.java:117) ~[?:?]
        at org.elasticsearch.xpack.watcher.transport.actions.execute.TransportExecuteWatchAction.masterOperation(TransportExecuteWatchAction.java:72) ~[?:?]
        at org.elasticsearch.action.support.master.TransportMasterNodeAction.masterOperation(TransportMasterNodeAction.java:88) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.action.support.master.TransportMasterNodeAction$AsyncSingleAction$2.doRun(TransportMasterNodeAction.java:167) ~[elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:672) [elasticsearch-6.2.2.jar:6.2.2]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-6.2.2.jar:6.2.2]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_161]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_161]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_161]
Caused by: java.lang.IllegalArgumentException: mustache engine does not know how to handle context [xpack_executable]
        at org.elasticsearch.script.mustache.MustacheScriptEngine.compile(MustacheScriptEngine.java:65) ~[?:?]
        at org.elasticsearch.script.ScriptService.compile(ScriptService.java:335) ~[elasticsearch-6.2.2.jar:6.2.2]
        ... 22 more

The same watch definition is compiling in ES 5.6.3, but then it simply generates a string with value if a PagedBytesReference object reference, rather than original JSON value as base64 string.

1 Like

the body field of the webhook must be a single string.

It should look like this

"body" : "{{#toJson}}ctx.payload.my_field{{/toJson}}"

Before that you need a script transform, that creates the same data structure, that you created in the body with the body, watch_id, execution_time fields.

Hope that makes sense.

Thanks for the reply.
The problem is that we want to send the data not as JSON but Base64 array string.

Doing mustache transform of payload hits to JSON works fine in ES 5.6.3, but consecutive painless script transform (or even final body) receives the value as org.elasticsearch.common.bytes.PagedBytesReference:

      "chain": {
        "results": [
          {
            "type": "script",
            "status": "success",
            "payload": {
              "_value": "W3siX2luZGV4Ijoid2F0Y2hlcl93ZWJob29rX3Rlc3RfZGF0YV8xIiwiX3R5cGUiOiJsb2dzIiwiX3NvdXJjZSI6eyJAdGltZXN0YW1wIjoiMjAxOC0wNC0wOSIsIm1lc3NhZ2UiOiJIaSB0aGVyZSEgdGhpcyBpcyBcImNvbW1hXCIgZXhhbXBsZSwgYW5kIFwiZG91YmxlIHF1b3Rlc1wiIGFsc28uIFdlIGhhdmUgX2lkPTEuXG4iLCJob3N0X25hbWUiOiJsb2NhbGhvc3QifSwiX2lkIjoiMSIsInNvcnQiOlsxNTIzMjMyMDAwMDAwXSwiX3Njb3JlIjpudWxsfSx7Il9pbmRleCI6IndhdGNoZXJfd2ViaG9va190ZXN0X2RhdGFfMSIsIl90eXBlIjoibG9ncyIsIl9zb3VyY2UiOnsiQHRpbWVzdGFtcCI6IjIwMTgtMDQtMDlUMTE6MTA6MzBaIiwibWVzc2FnZSI6IkhpIHRoZXJlISB0aGlzIGlzIHNlY29uZCBcImNvbW1hXCIgZXhhbXBsZSwgYW5kIFwiZG91YmxlIHF1b3Rlc1wiIGFsc28uIFdlIGhhdmUgX2lkPTIuXG4iLCJob3N0X25hbWUiOiJsb2NhbGhvc3QyIn0sIl9pZCI6IjIiLCJzb3J0IjpbMTUyMzI3MjIzMDAwMF0sIl9zY29yZSI6bnVsbH0seyJfaW5kZXgiOiJ3YXRjaGVyX3dlYmhvb2tfdGVzdF9kYXRhXzEiLCJfdHlwZSI6ImxvZ3MiLCJfc291cmNlIjp7IkB0aW1lc3RhbXAiOjE1MjMyNzM5NjcwMjUsIm1lc3NhZ2UiOiJIaSB0aGVyZSEgdGhpcyBpcyB0aGlyZCBcImNvbW1hXCIgZXhhbXBsZSwgYW5kIFwiZG91YmxlIHF1b3Rlc1wiIGFsc28uIFdlIGhhdmUgX2lkPTxTb21lIHJhbmRvbWx5IGdlbmVyYXRlZCB2YWx1ZT4uXG4iLCJob3N0X25hbWUiOiJsb2NhbGhvc3QyIn0sIl9pZCI6IkFXS3FjUWFhQUNwNUxHSEsyWWlRIiwic29ydCI6WzE1MjMyNzM5NjcwMjVdLCJfc2NvcmUiOm51bGx9XQ=="
            }
          },
          {
            "type": "script",
            "status": "success",
            "payload": {
              "payload": "org.elasticsearch.common.bytes.PagedBytesReference@c4c0ae52"
            }
          }
        ]
      }

The same logic throws compilation error in ES 6.x as depicted in my first post.

the first toJson in the script transform is not needed, unless I am missing somthing obvious here

1 Like

Thanks a lot for your help.
ctx.payload.hits.hits is JSON and I had to convert it to String before encoding.
Got it working with below transform script:

  "transform": {
    "script": {
      "source": "return [ 'payload': ctx.payload.hits.hits.toString().encodeBase64() ]",
      "lang": "painless"
    }
  },
  "webhook": {
    "scheme": "http",
    "host": "webhookEndPointServer",
    "port": 80,
    "method": "post",
    "path": "/raise",
    "params": {},
    "body": {
      "source": {
        "payload": {
          "execution_time": "{{ctx.execution_time}}",
          "watch_id": "{{ctx.watch_id}}",
          "body": "{{ctx.payload}}"
        }
      },
      "lang": "mustache",
      "options": {
        "content_type": "application/json; charset=UTF-8"
      }
    }
  }

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.