elastic/elasticsearch · error · ScriptException

compile error

Error message

compile error

What it means

This is the catch-all wrapper thrown by convertToScriptException whenever ANY underlying error occurs while compiling a Painless script (syntax, type, reference, etc.). The original throwable is wrapped via ErrorCauseWrapper.maybeWrap and rethrown as a ScriptException whose message is the literal string 'compile error'. The real diagnostic is in the cause and in the scriptStack list, which contains a snippet of the failing script region plus a '^---- HERE' pointer line computed from the WriterConstants.CLASS_NAME stack frame.

Source

Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java:497

                        snippet.append(" ...");
                    }
                    scriptStack.add(snippet.toString());
                    StringBuilder pointer = new StringBuilder();
                    if (startOffset > 0) {
                        pointer.append("    ");
                    }
                    for (int i = startOffset; i < offset; i++) {
                        pointer.append(' ');
                    }
                    pointer.append("^---- HERE");
                    scriptStack.add(pointer.toString());
                    pos = new ScriptException.Position(originalOffset, startOffset, endOffset);
                }
                break;
            }
        }
        Throwable cause = ErrorCauseWrapper.maybeWrap(t);
        throw new ScriptException("compile error", cause, scriptStack, scriptSource, PainlessScriptEngine.NAME, pos);
    }

    // very simple heuristic: +/- 25 chars. can be improved later.
    private static int getPreviousStatement(int offset) {
        return Math.max(0, offset - 25);
    }

    private static int getNextStatement(String scriptSource, int offset) {
        return Math.min(scriptSource.length(), offset + 25);
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the ScriptException.getScriptStack() and getCause() — the snippet and '^---- HERE' pointer pinpoint the failing offset in the script.
  2. Fix the syntax/type/reference error in the script text indicated by the cause.
  3. If the cause references an un-whitelisted method, replace it with an allowed Painless API or add an allowlist entry if you maintain a custom context.
  4. Re-run with the corrected script; the 'compile error' wrapper disappears once the underlying compile succeeds.

Example fix

// before (invalid: undeclared variable)
{"script": {"source": "doc['price'].value * faktor"}}
// after
{"script": {"source": "doc['price'].value * factor"}}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate script source before sending: a lightweight pre-check is not possible generically,
// but you can catch the wrapped exception and surface the cause.
try {
    scriptService.compile(script, context);
} catch (ScriptException e) {
    // real error is e.getCause() and e.getScriptStack()
}

Try / catch

try {
    CompiledScript compiled = scriptService.compile(script, ScriptContext.Standard.SEARCH);
} catch (ScriptException e) {
    List<String> stack = e.getScriptStack(); // snippet + '^---- HERE' pointer
    Throwable cause = e.getCause();          // underlying compile error
    log.warn("Painless compile failed: {} | stack:{}", cause, stack);
    throw e;
}

Prevention

When it happens

Trigger: Compiling any Painless script that has a syntax error, references an undefined variable/function, performs a disallowed cast, or uses an un-whitelisted API. The trigger is compile() failing and control reaching the throw at line 497 of PainlessScriptEngine. Common entry points: _scripts/painless/_execute, inline scripts in _search, runtime fields, ingest pipelines, or any ScriptService.compile call.

Common situations: Typo in a Painless script field name; using a Java API that is not whitelisted for Painless; version upgrade that removed or renamed a previously allowed method; passing the wrong script context; dynamic/scripted_field with invalid syntax.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/eb4d90881a6d9f47. Report an issue: GitHub.