stamparm/maltrail · error · ConfigError
invalid USERS entry ' ' [?] (hint: add whitespace at start…
Error message
invalid USERS entry '{line}'
[?] (hint: add whitespace at start of line) What it means
The sensor's config parser (parse_raw) rejects a whitespace-less line inside a USERS array that contains characters other than alphanumerics or underscore. Because USERS entries like admin: secret would contain ':' with no space separator, this is almost certainly a malformed USERS block — and the parser helpfully suggests the likely cause: the line is missing its leading whitespace, so it isn't being treated as an array entry at all.
Solutions
- Indent the USERS entry so the parser treats it as an array element (add whitespace at the start of the line)
- Ensure each entry has the expected separator with spacing (e.g. `admin secret`) rather than flush-left `admin:secret`
- Check the line directly above: an unindented line ends the current array context
- Re-run the sensor after fixing; the same check covers other arrays with the generic message
Example fix
// before (config)
USERS
admin: secret
// after
USERS
admin secret Defensive patterns
Strategy: validation
Validate before calling
import re
for i, line in enumerate(open("sensor.conf")):
stripped = line.rstrip("\n")
if 'USERS' in stripped or (stripped and not stripped[0].isspace()):
continue
if stripped.strip() and not re.fullmatch(r'[A-Za-z0-9_ ]+', stripped.strip()):
print(f"check line {i+1}: {stripped!r}") Prevention
- Always indent entries inside USERS blocks
- Use space-separated user entries, not colon-joined
- Validate the config by loading it once in CI
When it happens
Trigger: Loading the sensor config when a line under [USERS]-style array context has no space, contains non-[A-Za-z0-9_] characters (like ':' in user:pass), and the current array being parsed is USERS — typically the entry lost its indentation.
Common situations: Writing `admin: secret` flush-left inside a USERS block instead of indented; copy-pasting entries from docs without indentation; converting an old config format where entries had different syntax.
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
- invalid configuration
- invalid configuration value for 'UPDATE_PERIOD
- missing configuration file
- missing mandatory option
- invalid configuration value for 'LOG_SERVER
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/d966d568b0a3f98d.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/config.rs:441
// re.sub(r"\s*#.*", "", line)
let line = match line.find('#') {
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)