Loading

Debug script score calculation errors in Painless

When you use script_score with type double, the script can return unexpected null values, negative values, 0.0, or Infinity, causing documents to receive a score of 0 or be excluded from results entirely. This commonly occurs when field access patterns don't account for missing values or when mathematical operations result in null propagation.

Follow these guidelines to avoid scoring calculation errors in your Painless scripts:

  • Mathematical safety: Validate inputs for functions like Math.log().
  • Default values: Provide meaningful defaults for missing fields to maintain consistent scoring.
  • Minimum scores: Ensure scripts return positive values to avoid zero scores.
  • Null handling: Mathematical operations with null values propagate null throughout the calculation.

For details, refer to the following sample error, solution, and the result when the solution is applied to sample documents.

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "script_score script returned an invalid score [-Infinity] for doc [0]. Must be a non-negative score!"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "products",
        "node": "CxMTEjvKSEC0k0aTr4OM3A",
        "reason": {
          "type": "illegal_argument_exception",
          "reason": "script_score script returned an invalid score [-Infinity] for doc [0]. Must be a non-negative score!"
        }
      }
    ],
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "script_score script returned an invalid score [-Infinity] for doc [0]. Must be a non-negative score!",
      "caused_by": {
        "type": "illegal_argument_exception",
        "reason": "script_score script returned an invalid score [-Infinity] for doc [0]. Must be a non-negative score!"
      }
    }
  },
  "status": 400
}
		
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
          double price = 0.0;
          double rating = 5.0;

          return Math.log(price) * rating;
        """
      }
    }
  }
}
		
  1. Simulating problematic calculation

The error occurs because of mathematical edge cases in calculations:

  1. Math.log() with zero or negative values: Math.log(0) returns negative infinity, Math.log(-x) returns NaN.
  2. Division by zero: Operations such as x/0 throw an arithmetic_exception.
  3. NaN propagation: Any mathematical operation involving NaN results in NaN.
  4. Infinity calculations: Operations with infinity often result in NaN or unexpected values.

When a script returns NaN, negative infinity, or other invalid numbers, Painless converts the score to 0.0, causing unexpected ranking behavior.

Always validate mathematical inputs and handle edge cases:

GET products/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
          double price = 0.0;
          double rating = 5.0;

          double safePrice = Math.max(price, 1.0);

          // Calculate score with safety checks
          double logPrice = Math.log(safePrice);
          double score = logPrice * rating;

          // Handle NaN or infinity results
          if (Double.isNaN(score) || Double.isInfinite(score)) {
            return 1.0;
          }

          return Math.max(score, 0.1);
        """
      }
    }
  }
}
		
  1. Ensure > 0 for log
  2. Ensure a minimum positive score
POST products/_doc
{
  "name": "Premium Laptop",
  "price": 999.99,
  "rating": 4.7,
  "category": "electronics"
}

POST products/_doc
{
  "name": "Free Software",
  "price": 0,
  "rating": 5.0,
  "category": "software"
}
		
{
  ...,
  "hits": {
    ...,
    "hits": [
      {
        "_index": "products",
        "_id": "j6gZNZkB0eMypkDYmmSC",
        "_score": 0.1,
        "_source": {
          "name": "Premium Laptop",
          "price": 999.99,
          "rating": 4.7,
          "category": "electronics"
        }
      },
      {
        "_index": "products",
        "_id": "kKgZNZkB0eMypkDYn2SP",
        "_score": 0.1,
        "_source": {
          "name": "Free Software",
          "price": 0,
          "rating": 5,
          "category": "software"
        }
      }
    ]
  }
}