ErrLookup › Background articles › Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries
Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries
Config validation failed is the error family a tool raises when it parses your settings — pnpm-workspace.yaml, mise.toml, ruff --config, k6 script options, config.toml, or environment variables like RUSTFS_SCANNER_* — and rejects them before any real work runs. You meet it at startup, install, build, boot, or config-update time as messages like "invalid scanner config value for {key}: {value} ({reason})", "timeoutMs must be a positive integer", or "Failed to validate drainer configuration". This article covers the mechanism shared by the 113 documented records: a validation pass that checks types, ranges, names, paths, cross-field invariants, and backend capability after parsing succeeds but before the tool commits to work.
Distilled from 113 documented records across 19 repositories.
Background
These errors come from a dedicated validation layer that sits between config parsing and real work. Parsing (serde, clap, TOML and JSON readers) succeeds first; a hand-written guard runs second. Hyperswitch calls conf.validate() after deserialization and panics via expect when a structural check fails; RustFS runs WebDavConfig::validate() and ObjectDataCacheConfig::validate() before the services start; mise checks bin and rename_exe options the moment they are read; openhuman validates agent-tier hierarchies at registry load; pnpm compiles exclude lists into a version policy before any install work runs. The shared philosophy is fail fast: mise refuses a whole firewall request when one rule is bad rather than write a partial ruleset, k6 aborts startup when cloud-required tags are missing because aggregation would be incomplete, and pnpm rejects a reserved registry alias at startup because the named-registry resolver runs last, so the alias would be silently shadowed anyway.
From the caller's side the family usually names the offender, but the surface and timing are library-specific. RustFS's scanner error interpolates the exact key, value, and reason; pnpm derives an INVALID_<KEY> code from the setting key and wraps the parser's message; k6 joins every problem into one bulleted report and exits with code 104; Chroma names the offending kwarg or non-mutable key. How it surfaces varies: a Rust panic (Hyperswitch), a process exit code (k6), an S3 InvalidArgument on every quota-checked write until stored JSON is repaired (RustFS quota), a boot-time bail (openhuman), a warning-and-skip (mise launchd agent names), or a deliberately generic message that omits detail because config errors can embed credentials (CodeWhale, whose --json path prints the redacted diagnostic instead). A few validators run at update time rather than startup: Chroma's BM25 function rejects config updates outside its six mutable keys, and RustFS re-parses persisted quota JSON on every admission check.
The guards protect invariants that later layers silently assume. mise's safe-relative-path and plain-file-name checks keep resolved binaries inside the install directory; RustFS rejects zero WebDAV caps because an unbounded accept loop is a resource-exhaustion hole, and rejects identity_keys_max == 1 because the identity index would evict the previous key on every fill and thrash; charset limits exist because rule and agent names become stable identifiers in iptables/nftables rules and launchd labels; Neon rejects a (resource_multiplier, spread_factor) pair whose product with (spread_factor + 1.0) reaches 1.0 because the cache-sizing formula becomes unsolvable; Chroma requires kwargs to be JSON primitives because configs must round-trip through serialization. Grammars are strict on purpose too: pnpm's exclude patterns accept bare names, name globs, and exact versions or version unions, and reject semver ranges and glob-with-version combinations by design.
Two cautions from the records. Detail availability differs by library: most messages pinpoint the field, but CodeWhale's text path intentionally discards the underlying error, and the fix is to re-run codewhale doctor --json for the redacted, actionable diagnostic. And at least one documented raise site is dead code: Chroma's 'not a valid hnsw config' wraps typing.cast, which never raises at runtime, so that specific error cannot actually fire — treat any hnsw config failure as coming from somewhere else, or from real validation added in a fork.
Common causes
- Wrong type or unparseable syntax. A value fails to parse as the expected type, or the file or inline value is syntactically invalid: non-numeric input for integer keys, unrecognized boolean words, invalid TOML in ruff --config, malformed config.toml, or TOML that parses but does not match the tool's settings schema.
- Value outside the accepted range. RustFS requires scanner delay within 0..=10000 and rejects identity_keys_max of 0 and 1; WebDAV rejects 0 for max_body_size, request_timeout_secs, and max_connections; caveman requires timeoutMs to be a positive safe integer, so 0, floats, NaN, and Infinity all fail even when 0 was meant as 'no timeout'.
- Empty required fields hidden by defaults. Serde defaults let an almost-empty config parse cleanly, and only validate() catches it. Hyperswitch's drainer dies on empty master_database fields or a blank drainer.stream_name; CodeWhale fleet specs reject empty or whitespace-only environment variable names.
- Disallowed names, prefixes, or patterns. pnpm rejects registry aliases that collide with reserved dependency-specifier prefixes (git, npm, jsr, file, ...) and exclude patterns that use semver ranges (^, ~, >=) or combine a name glob with a version; mise restricts firewall rule names and launchd agent names to ASCII letters, digits, '-', '_' (and '.' for agents), 1-64 bytes.
- Path values that escape the install directory. mise rejects absolute paths, '..' segments, drive prefixes, and empty strings in bin, and any path separator in rename_exe, because such values would resolve the binary outside the tool's install directory.
- Capability mismatch between config and backend. UFW cannot express SCTP or DCCP rules, so mise refuses the whole firewall request up front; mise oci build supports only apt and apk package managers; k6's cloud output requires the system tags proto/name, method, status, error, check, and group, which a restricted systemTags set can omit.
- Coupled cross-field invariants. Neon's FileCache requires resource_multiplier * (spread_factor + 1.0) < 1.0 or the sizing formula is unsolvable; RustFS WebDAV requires an existing cert_dir when TLS is enabled, and existing paths for cert_dir and ca_file.
- Update-time and serialization constraints. Chroma's BM25 function accepts live updates only to k, b, avg_doc_length, token_max_length, stopwords, include_tokens, and requires kwargs to be JSON primitives — None is rejected, not treated as a null; RustFS fails every quota-checked write on a bucket whose stored quota_config_json no longer parses as BucketQuota JSON.
What usually fixes it
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
Go deeper
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Documented occurrences
- INVALID_${key.replace(/([A-Z])/g, '_$1').toUpperCase()} (resolves to INVALID_MINIMUM_RELEASE_AGE_EXCLUDE / INVALID_TRUST_POLICY_EXCLUDE): Invalid value in ${key}: ${(err as { message: string }).message} (pnpm/pnpm)
- agent `{parent}` ({ptier}) lists `{child}` ({ctier}) in subagents — {reason} (tinyhumansai/openhuman)
- RESERVED_NAMED_REGISTRY_NAME: '${alias}' cannot be used as a named registry alias: it is a reserved dependency specifier prefix. (pnpm/pnpm)
- InvalidArgument: Invalid quota configuration: {reason} (rustfs/rustfs)
- {option}: '{path}' must be a safe relative path (no absolute paths or parent directories) (jdx/mise)
- ValueValidation: invalid value '{invalid_value}' for '{invalid_arg}' (astral-sh/ruff)
- doctor configuration validation failed; details omitted because configuration errors may contain credential material (Hmbown/CodeWhale)
- Updating '{key}' is not supported for {NAME} (chroma-core/chroma)
- cli feature is not enabled (jdx/mise)
- Failed to validate drainer configuration (juspay/hyperswitch)
- {option}: '{name}' must be a plain file name (no path separators or parent directories) (jdx/mise)
- agent `{parent}` is a `worker` tier and must not list `{child}` in its subagents — workers are leaf executors. (tinyhumansai/openhuman)
- invalid WebDAV configuration: {0} (rustfs/rustfs)
- Failed to update flow (Mintplex-Labs/anything-llm)
- oci mount_point must not be empty (jdx/mise)
- object data cache identity_keys_max must be greater than 0 (rustfs/rustfs)
- firewall rule name '{name}' must contain only ASCII letters, numbers, '-' or '_' (jdx/mise)
- Keyword argument {key} is not a primitive type (chroma-core/chroma)
- object data cache identity_keys_max must be at least 2 (rustfs/rustfs)
- fleet task {} environment variable name cannot be empty (Hmbown/CodeWhale)
…and 93 more across the corpus — use search.
Honest provenance: generated on 2026-08-18 from AI-assisted analysis of the linked records. See how records are made.