Debug runtime field exception errors in Painless
Elastic Cloud Serverless projects are autoscaled environments, fully managed by Elastic and available on Elastic Cloud. Availability This functionality is generally available and ready for production usage. Serverless interfaces and procedures might differ from classic Elastic Stack deployments. The Elastic Stack includes Elastic's core products such as Elasticsearch, Kibana, Logstash, and Beats. Availability This functionality is generally available and ready for production usage. Unless stated otherwise on the page, this functionality is available when your Elastic Stack is deployed on Elastic Cloud Hosted, Elastic Cloud Enterprise, Elastic Cloud on Kubernetes, and self-managed environments. This documentation corresponds to the latest patch available for each minor version. If you're not using the latest patch, check the release notes for changes.
Serverless
Generally available
Stack
Generally available
When you create runtime mappings in a Painless script, using return instead of emit to output values leads to compilation errors, as runtime field scripts require the emit() function to produce field values.
Follow these guidelines to avoid runtime field exceptions in your Painless scripts:
- Runtime field scripts must use
emit()to output values, notreturn. emit()can be called multiple times in a script to emit multiple values.
For details, refer to the following sample error, solution, and the result when the solution is applied.
{
"error": {
"root_cause": [
{
"type": "class_cast_exception",
"reason": "class_cast_exception: Cannot cast from [java.lang.String] to [void]."
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "users",
"node": "hupWdkj_RtmThGjNUiIt_w",
"reason": {
"type": "script_exception",
"reason": "compile error",
"script_stack": [
"""... Doe";
return firstName + " " + lastNam ...""",
" ^---- HERE"
],
"script": """
String firstName = "John";
String lastName = "Doe";
return firstName + " " + lastName;
""",
"lang": "painless",
"position": {
"offset": 92,
"start": 67,
"end": 117
},
"caused_by": {
"type": "class_cast_exception",
"reason": "class_cast_exception: Cannot cast from [java.lang.String] to [void]."
}
}
}
],
"caused_by": {
"type": "class_cast_exception",
"reason": "class_cast_exception: Cannot cast from [java.lang.String] to [void]."
}
},
"status": 400
}
{
"runtime_mappings": {
"full_name": {
"type": "keyword",
"script": {
"source": """
String firstName = "John";
String lastName = "Doe";
return firstName + " " + lastName;
"""
}
}
}
}
Runtime field scripts use emit() to produce values, rather than return. The emit() function is specifically designed for runtime mappings to output field values, while return is used in other Painless contexts such as script queries or update scripts. The error occurs because runtime field scripts expect a void return type, but the script attempts to return a String value.
Replace return statements with emit() calls:
POST users/_search
{
"fields": [
{
"field": "*",
"include_unmapped": "true"
}
],
"runtime_mappings": {
"full_name": {
"type": "keyword",
"script": {
"source": """
String firstName = "John";
String lastName = "Doe";
emit(firstName + " " + lastName);
"""
}
}
}
}
{
...,
"hits": {
...,
"hits": [
{
...,
"_source": {
"user": {
"name": "Jane Doe"
}
},
"fields": {
"user.name.keyword": [
"Jane Doe"
],
"user_info": [
"incomplete: Jane Doe"
],
"user.name": [
"Jane Doe"
]
}
}
]
}
}