﻿---
title: Debug script score calculation errors in Painless
description: 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...
url: https://www.elastic.co/elastic/docs-builder/docs/3016/explore-analyze/scripting/painless-script-score-calculation-errors
products:
  - Elasticsearch
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available
---

# Debug script score calculation errors in Painless
When you use [`script_score`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3016/reference/query-languages/query-dsl/query-dsl-script-score-query) 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.

## Sample error

```json
{
  "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
}
```


## Problematic code

```json
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
          double price = 0.0; 
          double rating = 5.0;

          return Math.log(price) * rating;
        """
      }
    }
  }
}
```


## Root cause

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.

## Solution: Add mathematical safety checks

Always validate mathematical inputs and handle edge cases:
```json
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); 
        """
      }
    }
  }
}
```


## Sample documents

```json
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"
}
```


## Result

```json
{
  ...,
  "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"
        }
      }
    ]
  }
}
```