apache/seatunnel · error · IllegalArgumentException

maxLines must be >= 1

Error message

maxLines must be >= 1

What it means

MultilineAssembler's constructor validates that the buffer line cap is at least 1, because an assembler that retains zero lines could never emit an event. Throwing immediately at construction turns a misconfiguration into a fast, clear failure instead of silent misbehavior during file tailing.

Source

Thrown at seatunnel-edge-agent/seatunnel-edge-agent-connector/src/main/java/org/apache/seatunnel/edge/agent/connector/file/multiline/MultilineAssembler.java:78

    }

    private final Pattern pattern;
    private final MatchMode matchMode;
    private final boolean negate;
    private final int maxLines;
    private final List<LineElement> buffer;

    /**
     * @param regex pattern applied to each line's text (via {@code Pattern.matcher} {@code
     *     .find()})
     * @param matchMode AFTER or BEFORE semantics (see {@link MatchMode})
     * @param negate if true, pattern match is inverted
     * @param maxLines maximum number of lines to retain in the buffer before forcing a flush (must
     *     be {@code >= 1})
     */
    public MultilineAssembler(String regex, MatchMode matchMode, boolean negate, int maxLines) {
        if (maxLines < 1) {
            throw new IllegalArgumentException("maxLines must be >= 1");
        }
        this.pattern = Pattern.compile(Objects.requireNonNull(regex, "regex"));
        this.matchMode = Objects.requireNonNull(matchMode, "matchMode");
        this.negate = negate;
        this.maxLines = maxLines;
        this.buffer = new ArrayList<>();
    }

    /**
     * Feeds one physical line into the assembler.
     *
     * @return a new list containing the completed prior event if this line triggered a flush, or
     *     {@code null} if the line was only buffered and no event completed yet
     */
    public List<LineElement> addLine(LineElement line) {
        boolean matches = pattern.matcher(line.getText()).find();
        if (negate) {
            matches = !matches;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set maxLines to a positive integer (>= 1) in the constructor call or the underlying config
  2. Validate/clamp the config value when parsing agent.yaml before constructing the assembler
  3. Add a config-level check that rejects maxLines <= 0 with a message naming the config key

Example fix

// before
MultilineAssembler assembler = new MultilineAssembler(pattern, matchMode, false, maxLines);
// after
int safeMaxLines = Math.max(1, maxLines);
MultilineAssembler assembler = new MultilineAssembler(pattern, matchMode, false, safeMaxLines);
Defensive patterns

Strategy: validation

Validate before calling

if (maxLines < 1) {
    throw new IllegalArgumentException("maxLines must be >= 1, got: " + maxLines);
}
new MultilineAssembler(regex, matchMode, negate, maxLines);

Type guard

boolean isValidMaxLines(Integer v) { return v != null && v >= 1; }

Prevention

When it happens

Trigger: Calling new MultilineAssembler(regex, matchMode, negate, maxLines) with maxLines < 1 (typically 0 or a negative value parsed from a user-supplied multiline config option).

Common situations: agent.yaml multiline.max-lines set to 0 or a negative number by mistake; an int-parsed config default of 0 when the user forgot to set the value; off-by-one arithmetic when deriving maxLines from another setting.

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/c68d9fe9edc6d2d5. Report an issue: GitHub.