apache/seatunnel · error · IllegalArgumentException

error handler max_error_records must be non-negative, but…

Error message

error handler max_error_records must be non-negative, but was %s

What it means

IllegalArgumentException from ErrorHandlerConfigUtil.buildStageConfig when max_error_records is negative. The limit is an absolute count of tolerated row-level errors, so only non-negative longs are valid; 0 disables the threshold.

Solutions

  1. Set max_error_records = 0 to disable the record-count threshold (that is the 'unlimited' equivalent).
  2. Use a positive limit matching tolerable dirty-row volume.
  3. Audit global vs stage-level error-handler blocks for stray negative values.

Example fix

// before
error-handler { max_error_records = -1 }
// after
error-handler { max_error_records = 0 }
Defensive patterns

Strategy: validation

Validate before calling

long m = config.getLong("max_error_records");
if (m < 0) throw new IllegalArgumentException("max_error_records must be >= 0 (0 disables the threshold)");

Type guard

boolean isNonNegativeLong(Object v) { return v instanceof Number n && n.longValue() >= 0; }

Try / catch

try { buildStageConfig(stage, global); } catch (IllegalArgumentException e) { if (e.getMessage().contains("max_error_records")) { fixRecordsConfig(); } }

Prevention

When it happens

Trigger: Configuring env.error-handler.max_error_records (global or per stage) with a negative number, e.g. -1 intending 'unlimited'.

Common situations: Users using -1 to mean 'no limit' as in other systems; sign typo; templated configs filling in unset variables as -1.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/0b663ac69533c8fc. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/ErrorHandlerConfigUtil.java:80

        String modeStr = getString(stage, global, "mode", "DISABLE");
        ErrorHandlerMode mode = ErrorHandlerMode.fromString(modeStr);

        double maxErrorRatio = getDouble(stage, global, "max_error_ratio", 0.0d);
        if (maxErrorRatio < 0.0d || maxErrorRatio > 1.0d) {
            throw new IllegalArgumentException(
                    "error handler max_error_ratio must be between 0.0 and 1.0, but was "
                            + maxErrorRatio);
        }
        int maxErrorRatioMinRecords =
                getNonNegativeInt(
                        stage,
                        global,
                        "max_error_ratio_min_records",
                        DEFAULT_MAX_ERROR_RATIO_MIN_RECORDS);
        long maxErrorRecords = getLong(stage, global, "max_error_records", 0L);
        if (maxErrorRecords < 0L) {
            throw new IllegalArgumentException(
                    "error handler max_error_records must be non-negative, but was "
                            + maxErrorRecords);
        }

        int queueCapacity = getNonNegativeInt(stage, global, "queue_capacity", 10000);
        String overflowStr = getString(stage, global, "queue_overflow_policy", "FAIL");
        QueueOverflowPolicy overflowPolicy = QueueOverflowPolicy.fromString(overflowStr);

        boolean includeStacktrace = getBoolean(stage, global, "include_stacktrace", false);
        boolean includeOriginalData = getBoolean(stage, global, "include_original_data", false);

        String dataFormatStr = getString(stage, global, "original_data_format", "TEXT");
        if (!"TEXT".equalsIgnoreCase(dataFormatStr)) {
            throw new IllegalArgumentException(
                    "Unsupported original_data_format='"
                            + dataFormatStr
                            + "'. Current version only supports TEXT.");
        }

View on GitHub (pinned to cf67b549a7)