elastic/elasticsearch · error · IllegalArgumentException

[painless.regex.enabled] can only be set on node startup.

Error message

[painless.regex.enabled] can only be set on node startup.

What it means

PainlessScriptEngine.buildCompilerSettings throws this IllegalArgumentException when a per-script (per-request) compile parameter includes 'painless.regex.enabled'. Regex enabling is a security-sensitive node-level setting because regexes can be used for denial-of-service; Painless only reads it from the node's script context settings at startup. Passing it in the params map of an individual script/compilation request is rejected.

Source

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

            String value = copy.remove(CompilerSettings.MAX_LOOP_COUNTER);
            if (value != null) {
                compilerSettings.setMaxLoopCounter(Integer.parseInt(value));
            }

            value = copy.remove(CompilerSettings.PICKY);
            if (value != null) {
                compilerSettings.setPicky(Booleans.parseBoolean(value));
            }

            value = copy.remove(CompilerSettings.INITIAL_CALL_SITE_DEPTH);
            if (value != null) {
                compilerSettings.setInitialCallSiteDepth(Integer.parseInt(value));
            }

            value = copy.remove(CompilerSettings.REGEX_ENABLED.getKey());
            if (value != null) {
                throw new IllegalArgumentException("[painless.regex.enabled] can only be set on node startup.");
            }

            value = copy.remove(CompilerSettings.REGEX_LIMIT_FACTOR.getKey());
            if (value != null) {
                throw new IllegalArgumentException("[painless.regex.limit-factor] can only be set on node startup.");
            }

            if (copy.isEmpty() == false) {
                throw new IllegalArgumentException("Unrecognized compile-time parameter(s): " + copy);
            }
        }
        return compilerSettings;
    }

    private static ScriptException convertToScriptException(String scriptSource, Throwable t) {
        // create a script stack: this is just the script portion
        List<String> scriptStack = new ArrayList<>();
        ScriptException.Position pos = null;

View on GitHub (pinned to db6a809a66)

Solutions

  1. Set painless.regex.enabled in elasticsearch.yml or via the cluster settings API (script.painless.regex.enabled: limited/true), not in script params.
  2. Restart the node (or update the cluster setting) for the change to take effect.
  3. Remove painless.regex.enabled from the script's params map.

Example fix

// before (script params)
{"source": "doc['x'].value =~ /abc/", "params": {"painless.regex.enabled": true}}
// after (elasticsearch.yml)
script.painless.regex.enabled: limited
Defensive patterns

Strategy: validation

Validate before calling

// Do not include painless.regex.enabled in script params. Set it at node level:
// // PUT _cluster/settings {"persistent": {"script.painless.regex.enabled": "limited"}}

Prevention

When it happens

Trigger: Submitting a script with params that include {'painless.regex.enabled': true} via the _scripts API, an ingest pipeline, a runtime field, or any per-script compilation context. The buildCompilerSettings method strips known per-request keys and explicitly rejects the regex-enabled key.

Common situations: Trying to enable regex per-script after it was disabled cluster-wide. Copying node-level settings into script params by mistake. Tutorials or examples that conflate node settings with script params.

Related errors


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