stamparm/maltrail · error · ConfigError

invalid configuration

Error message

invalid configuration (line: '{line}')

What it means

parse_raw rejects any whitespace-less line containing characters outside [A-Za-z0-9_]. Such a line can't be a valid scalar/array entry or a section/array name, so the parser bails with the offending line. This is the generic sibling of the USERS-specific message: any malformed token-like line in the config triggers it.

Solutions

  1. Find the quoted line in your config and fix it to the expected format (space-separated key/value or plain alphanumeric name)
  2. Add a space between key and value if you wrote them glued together
  3. Remove or comment out stray punctuation/symbols on flush-left lines
  4. Diff against a known-good sensor.conf to spot the malformed line

Example fix

// before (config)
DEBUG=true
// after
DEBUG true
Defensive patterns

Strategy: validation

Validate before calling

import re
for i, line in enumerate(open("sensor.conf")):
    s = line.rstrip("\n")
    if s and ' ' not in s and not re.fullmatch(r'[A-Za-z0-9_]*', s):
        print(f"invalid token-like line {i+1}: {s!r}")

Prevention

When it happens

Trigger: A config line with no space character that contains any byte that is not ASCII alphanumeric or '_' — e.g. a stray 'admin:pass', punctuation, or an accidentally pasted command — while parsing the sensor config (called from load and its tests).

Common situations: Typo merging a key and value without a space (`DEBUG=true` style instead of space-separated); comment markers or symbols on a flush-left line; copy-paste artifacts; editing configs on Windows with a stray character.

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 stamparm/maltrail@77cfb06d76 (2026-09-13). Data as JSON: /api/errors/a1de7997321a1bc9. Report an issue: GitHub.

Appendix: source

Thrown at sensor/src/config.rs:443

            Some(idx) => {
                let mut cut = idx;
                while cut > 0 && line.as_bytes()[cut - 1].is_ascii_whitespace() {
                    cut -= 1;
                }
                &line[..cut]
            }
            None => line,
        };
        if line.trim().is_empty() {
            continue;
        }

        if !line.contains(' ') {
            if line.bytes().any(|c| !(c.is_ascii_alphanumeric() || c == b'_')) {
                if array.as_deref() == Some("USERS") {
                    bail!("invalid USERS entry '{line}'\n[?] (hint: add whitespace at start of line)");
                }
                bail!("invalid configuration (line: '{line}')");
            }
            let name = line.to_ascii_uppercase();
            out.insert(name.clone(), Value::Array(Vec::new()));
            array = Some(name);
            continue;
        }

        if let Some(arr) = array.clone() {
            if line.starts_with(' ') {
                let entry = line.trim().to_string();
                if let Some(Value::Array(items)) = out.get_mut(&arr) {
                    // IP_ALIASES is a server-side option, parsed here only so the sensor does
                    // not reject a shared configuration file. Its address part is not expanded.
                    items.push(entry);
                }
                continue;
            }
        }

View on GitHub (pinned to 77cfb06d76)