Null_pointer_exception when trying to access any object type of field using ctx._source

I have a index mapping like below

PUT /customer-index
{
  "mappings":{
    "properties":{
        "customers.id": {
        "type": "long"
      },
      "customers.name": {
        "type": "text",
        "norms": false
      },
      "customers.company": {
        "type": "text",
        "norms": false
      }
    }
  }
}

To this index, I have added two documents

PUT /customer-index/_doc/1
{
  "customers.company" : "google",
  "customers.id" : 1,
  "customers.name" : "adams"
}

PUT /customer-index/_doc/2
{
  "customers.company" : "apple",
  "customers.id" : 2,
  "customers.name" : "james"
}

Now I am trying to use update by query to update company to samsung where id is 2 . In real scenario, I have to update multiple docs in multiple indexes where id matches, that is why I am using update by query. But for simplicity, I have posted like this

POST /customer-index/_update_by_query
{
  "script": {
    "source": "ctx._source.customers.company = params.company",
    "lang": "painless",
    "params": {
      "company": "samsung"
    }
  },
  "query": {
    "term": {
      "customers.id": 2
    }
  }
}

But it is always throwing null_pointer_exception

{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "runtime error",
        "script_stack": [
          "ctx._source.customers.company = params.company",
          "                     ^---- HERE"
        ],
        "script": "ctx._source.customers.company = params.company",
        "lang": "painless",
        "position": {
          "offset": 21,
          "start": 0,
          "end": 46
        }
      }
    ],
    "type": "script_exception",
    "reason": "runtime error",
    "script_stack": [
      "ctx._source.customers.company = params.company",
      "                     ^---- HERE"
    ],
    "script": "ctx._source.customers.company = params.company",
    "lang": "painless",
    "position": {
      "offset": 21,
      "start": 0,
      "end": 46
    },
    "caused_by": {
      "type": "null_pointer_exception",
      "reason": "Cannot invoke \"Object.getClass()\" because \"callArgs[0]\" is null"
    }
  },
  "status": 400
}

Adding a null check can avoid this error but my question is why I am getting null_pointer_exception when I have the document present in the index. I have checked at lot of places but still no luck. Please help.

Hi @ankitpandoh

I think maybe there is a problem in modeling the index. If it is a customer index, you could simplify it like this:

PUT /customer-index
{
  "mappings":{
    "properties":{
        "id": {
        "type": "long"
      },
      "name": {
        "type": "text",
        "norms": false
      },
      "company": {
        "type": "text",
        "norms": false
      }
    }
  }
}


PUT /customer-index/_doc/1
{
  "company" : "google",
  "id" : 1,
  "name" : "adams"
}

PUT /customer-index/_doc/2
{
  "company" : "apple",
  "id" : 2,
  "name" : "james"
}


POST /customer-index/_update_by_query
{
  "script": {
    "source": "ctx._source.company = params.company",
    "lang": "painless",
    "params": {
      "company": "samsung"
    }
  },
  "query": {
    "term": {
      "id": 2
    }
  }
}

That way the update-by-query will work.

Yes, that would work. Also, There was a mistake that in mappings, I didn't define customer's type. I should have defined it as type Object. I thought, when using the dot notation, it is implicit that customers is of type object. But that is not the case it seems.
@val suggested correct way of using such fields on my post on stackoverflow and that also worked for me.

ctx._source['customers.company']

Hi @RabBit_BR

I dig a little deeper and found out below things. I will try to explain it with an example.
Let's create 2 indexes, customer-index-10 and customer-index-20.

PUT /customer-index-10
{
  "mappings": {
    "properties": {
      "customers": {
        "type": "object",
        "properties": {
          "id": {
            "type": "long"
          },
          "name": {
            "type": "text",
            "norms": false
          },
          "company": {
            "type": "text",
            "norms": false
          }
        }
      }
    }
  }
}
PUT /customer-index-20
{
  "mappings": {
    "properties": {
      "customers.id": {
        "type": "long"
      },
      "customers.name": {
        "type": "text",
        "norms": false
      },
      "customers.company": {
        "type": "text",
        "norms": false
      }
    }
  }
}

If you invoke the _mapping API on both the indexes, it will return the same result which means in both the cases customer will be treated as type object. But the way update by query works in both the indexes that is different.

for index /customer-index-10, a script like below will work

"source" : "ctx._source.customers.name = 'updated name'"

But for index /customer-index-20, the above script will throw Null Pointer Exception and below script will work

"source" : "ctx._source['customers.name'] = 'updated name'"

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