Update dynamic document field from params in Painless

I am trying to write a stored script that will iterate through the params and update the ctx._source fields from those parameters. I can't seem to figure out the correct way to do this without hardcoding the field names (e.g. ctx._source.field).

POST _scripts/update-on-version
  "script": {
    "lang": "painless",
    "code": "if (ctx._source.myVersion == null || ctx._source.myVersion <= params.myVersion) { for (entry in params.entrySet()) { ctx._source.put(entry.getKey(),entry.getValue()) } } else { ctx.op = 'none' }"

POST service/service/2b38607f-e626-4a9e-a0ac-322bde377548/_update
  "scripted_upsert": true,
    "script" : {
        "stored": "update-on-version",
        "params": {
          "myVersion": 1294698,
          "firstName": "Testname1",
          "lastName": "Testname1"

  "error": {
    "root_cause": [
        "type": "remote_transport_exception",
        "reason": "[node-01][][indices:data/write/update[s]]"
    "type": "illegal_argument_exception",
    "reason": "Object has already been built and is self-referencing itself"
  "status": 400

@jeremylyman can you provide the stacktrack of the error as well?

@Jack_Conradson can you take a look at this?


So when I test your code snippet locally the code compiles and seems to do what's expected. However when running with an ES node I'm guessing you're somehow hitting this ( https://github.com/elastic/elasticsearch/issues/20540 ). A full stacktrace would be helpful here as @s1monw requested. But I'm also not 100% sure what would be self-referential exactly. It would be helpful if you could run Debug.explain on entry.getKey() and entry.getValue() just to be sure these are what you're expecting them to be as described here ( https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-debugging.html ).

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