Fluent Bit Config Validator
Validates syntax, checks pipeline tag connections, detects security misconfigurations, audits best practices, and performs dry-run testing for Fluent Bit configurations. Use this skill when working with Fluent Bit config files, validating syntax, checking for best practices, identifying security issues, performing dry-run testing, or troubleshooting configuration-related errors.
npx skills add github:pantheon-org/tekhne --skill ci-cd--fluentbit--validatorOverview
This skill provides a comprehensive validation workflow for Fluent Bit configurations, combining syntax validation, semantic checks, security auditing, best practice enforcement, and dry-run testing. Validate Fluent Bit configs with confidence before deploying to production.
Philosophy
- Validate in stages, because each stage catches a different class of fault and a pass at one stage says nothing about the next.
- Treat tag routing as part of correctness: a config that parses can still drop every record.
- Keep secrets out of config files; reference environment variables instead.
- Propose fixes and wait for approval; never change a config the user has not agreed to change.
- Prefer the single
--check allrun, and drop to individual checks only to debug one stage.
When to Use
- Validating an existing Fluent Bit configuration file before deployment
- Checking that INPUT tags reach FILTER and OUTPUT
Matchpatterns - Auditing a config for hardcoded credentials, disabled TLS or exposed network listeners
- Reviewing memory limits, flush intervals and storage settings
- Running a
fluent-bit --dry-runparse check - Verifying output from the fluentbit-generator skill
When Not to Use
- Generating a new Fluent Bit configuration from requirements (use fluentbit-generator)
- Validating Kubernetes manifests, Helm charts or Dockerfiles
- Debugging a running Fluent Bit process from its runtime logs
- Checking configs for other log shippers such as Fluentd, Logstash or Vector
Validation Workflow
Follow this sequential validation workflow. Each stage catches different types of issues.
Recommended: For comprehensive validation, use
--check allwhich runs all validation stages in sequence:python3 scripts/validate_config.py --file <config-file> --check all
Validation Stages Summary
| Stage | Check Type | What It Validates |
|---|---|---|
| 1 | structure |
Section headers, key-value format, brackets, indentation, encoding |
| 2 | sections |
Required fields, valid plugins, field values per section type |
| 3 | tags |
INPUT tags match FILTER/OUTPUT patterns, no orphaned sections |
| 4 | security |
Hardcoded credentials, TLS config, file permissions, network exposure |
| 5 | performance |
Memory limits, flush intervals, compression, buffer sizes |
| 6 | best-practices |
HTTP server, retry limits, storage config, environment variables |
| 7 | dry-run |
Config parsing, plugin loading, file permissions (requires fluent-bit binary) |
Individual check usage (for debugging specific issues):
python3 scripts/validate_config.py --file <config-file> --check <stage-type>
Detailed section validation rules: See references/SECTION-RULES.md for comprehensive requirements, valid plugins, field specifications, and best practices for SERVICE, INPUT, FILTER, OUTPUT, and PARSER sections
Tag Consistency Check
Validates: INPUT tags match FILTER Match patterns; FILTER tags match OUTPUT Match patterns; no orphaned filters or outputs; wildcard usage is correct.
Example:
[INPUT]
Tag kube.* # Produces: kube.var.log.containers.pod.log
[FILTER]
Match kube.* # Matches: ✅
[OUTPUT]
Match app.* # Matches: ❌ No logs will reach this output
Security Audit
Checks:
- Hardcoded credentials: HTTP_User/Passwd, AWS keys, API tokens in plain text
- TLS configuration: TLS disabled;
tls.verify Off; missing certificate files - File permissions: DB and parser files readable/writable
- Network exposure: INPUTs listening on 0.0.0.0 without auth; HTTP_Server exposed without auth
Auto-fix pattern:
# Before (insecure)
[OUTPUT]
HTTP_User admin
HTTP_Passwd password123
# After (secure)
[OUTPUT]
HTTP_User ${ES_USER}
HTTP_Passwd ${ES_PASSWORD}
Performance Analysis
Key checks:
Mem_Buf_Limitset on all tail inputsstorage.total_limit_sizeset on outputs- Flush interval appropriate (1–5s)
Skip_Long_Lines On; compression on network outputs- Kubernetes:
Buffer_Size 0for kubernetes filter recommended
Dry-Run Testing
fluent-bit -c <config-file> --dry-run
Catches: config parsing errors, plugin loading errors, parser syntax errors, file permission issues, missing dependencies.
If fluent-bit binary is not available: skip this stage, document that dry-run was skipped, and recommend testing in a development environment.
Documentation Lookup
Try context7 MCP first:
Use mcp__context7__resolve-library-id with "fluent-bit"
Then use mcp__context7__get-library-docs with:
- context7CompatibleLibraryID: /fluent/fluent-bit-docs
- topic: "<plugin-type> <plugin-name> configuration"
- page: 1
Fallback to WebSearch:
Search query: "fluent-bit <plugin-type> <plugin-name> configuration parameters site:docs.fluentbit.io"
Report and Fix Issues
1. Summarize all issues:
Validation Report for fluent-bit.conf
=====================================
Errors (3):
- [Line 15] OUTPUT elasticsearch missing required parameter 'Host'
- [Line 25] FILTER Match pattern 'app.*' doesn't match any INPUT tags
- [Line 8] INPUT tail missing Mem_Buf_Limit (OOM risk)
Warnings (2):
- [Line 30] OUTPUT elasticsearch has hardcoded password (security risk)
- [Line 12] INPUT tail missing DB file (no crash recovery)
Info (1):
- [Line 3] SERVICE Flush interval is 10s (consider reducing for lower latency)
Best Practices (2):
- Consider enabling HTTP_Server for health checks
- Consider enabling compression on OUTPUT elasticsearch
2. Categorize by severity:
- Errors (must fix): Configuration won’t work, Fluent Bit won’t start
- Warnings (should fix): Configuration works but has issues
- Info (consider): Optimization opportunities
- Best Practices: Recommended improvements
3. Propose specific fixes:
# Fix 1: Add missing Host parameter
[OUTPUT]
Name es
Match *
Host elasticsearch.logging.svc # Added
Port 9200
# Fix 2: Add Mem_Buf_Limit to prevent OOM
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Mem_Buf_Limit 50MB # Added
# Fix 3: Use environment variable for password
[OUTPUT]
Name es
HTTP_User admin
HTTP_Passwd ${ES_PASSWORD} # Changed from hardcoded
4. Get user approval via AskUserQuestion
5. Apply approved fixes using Edit tool
6. Re-run validation to confirm
7. Provide completion summary (fixed issues, per-check pass/fail status, and overall validation result)
8. Report-only summary (when the user chooses not to apply fixes):
📋 Validation Report Complete - No fixes applied
Summary:
- Errors: 2 (must fix before deployment)
- Warnings: 16 (should fix)
- Info: 15 (optimization suggestions)
Critical Issues Requiring Attention:
- [Line 5] Invalid Log_Level 'invalid_level'
- [Line 52] [OUTPUT opentelemetry] missing required parameter 'Host'
Recommendations:
- Review the errors above before deploying this configuration
- Consider addressing warnings to improve reliability and security
- Run validation again after manual fixes: python3 scripts/validate_config.py --file <config> --check all
Integration with fluentbit-generator
This validator is automatically invoked by the fluentbit-generator skill after generating configurations. It can also be used standalone to validate existing configurations.
Generator workflow:
- Generate configuration using fluentbit-generator
- Automatically validate using fluentbit-validator
- Fix any issues found
- Re-validate until all checks pass
- Deploy with confidence
Anti-Patterns
NEVER validate config syntax without checking tag routing
WHY: A configuration that parses without errors can still drop all logs silently if no OUTPUT Match pattern covers the tags produced by the INPUTs. Syntax validation alone gives false confidence.
BAD: Confirm fluent-bit --dry-run passes and ship the configuration to production.
GOOD: Trace every INPUT tag through all FILTER and OUTPUT Match patterns, for example by running python3 scripts/validate_config.py --file <config-file> --check tags.
NEVER skip TLS certificate validation in output plugins
WHY: tls.verify Off is convenient for local testing but is frequently forgotten when promoting a config to production, leaving log data in transit exposed to interception or man-in-the-middle attacks.
BAD: tls.verify Off present in a production output plugin targeting an external log aggregator.
GOOD: tls.verify On with tls.ca_file /etc/ssl/certs/ca-certificates.crt (or the appropriate CA bundle for your environment).
NEVER use the same buffer path for multiple Fluent Bit instances
WHY: Overlapping storage.path directories corrupt the backpressure state database, causing one instance to consume or delete the other’s buffered records and resulting in duplicate or lost log delivery.
BAD: Two Fluent Bit daemonsets sharing /var/log/flb-storage/ as their storage path.
GOOD: Assign a distinct storage.path value to each Fluent Bit instance (e.g., /var/log/flb-storage-app/ and /var/log/flb-storage-infra/).
NEVER ignore pipeline tag connection warnings
WHY: An INPUT tag that no OUTPUT Match pattern covers causes Fluent Bit to silently drop those records. This is the most common root cause of “missing logs” production incidents and is invisible without explicit tag validation.
BAD: Dismiss unmatched tag warnings from the validator as noise and proceed with deployment.
GOOD: Treat any unmatched tag as a P1 configuration error; every INPUT tag must be covered by at least one OUTPUT Match pattern before the config is considered valid.
NEVER leave hardcoded credentials in a configuration file
WHY: Plain-text HTTP_User, HTTP_Passwd, AWS keys and API tokens end up in version control, container images and config maps where anyone with read access can recover them.
BAD: HTTP_Passwd password123 in an [OUTPUT] section.
GOOD: HTTP_Passwd ${ES_PASSWORD}, with the value supplied through the environment.
NEVER omit Mem_Buf_Limit on tail inputs
WHY: Without a memory buffer limit, a slow or unavailable output lets a tail input buffer records until the process runs out of memory.
BAD: An [INPUT] with Name tail and no Mem_Buf_Limit.
GOOD: Mem_Buf_Limit 50MB on every tail input.
NEVER apply fixes without user approval
WHY: Validation findings are proposals. Rewriting a config the user did not agree to change can alter routing or credentials in ways they did not review.
BAD: Edit the config file as soon as an error is found.
GOOD: Present the proposed fixes, ask for approval, apply only the approved ones, then re-run the validation.
NEVER skip the dry-run stage without recording that it was skipped
WHY: The dry-run is the only stage that loads plugins and parses the config with the real binary. Silently omitting it makes a partial validation look complete.
BAD: Report the configuration as valid after stages 1 to 6 on a host with no fluent-bit binary, without saying so.
GOOD: State that the dry-run was skipped because the binary is unavailable, and recommend testing in a development environment.
NEVER stop at the first error when reporting
WHY: Fixing one issue and re-running one at a time wastes cycles and hides related problems; users need the full list to plan the fix.
BAD: Report only the first failing check and abort.
GOOD: Run python3 scripts/validate_config.py --file <config-file> --check all, then group all findings into errors, warnings, info and best practices.
NEVER expose the HTTP server or network inputs without authentication
WHY: INPUTs listening on 0.0.0.0 and an exposed HTTP_Server let anyone on the network inject records or read internal metrics.
BAD: An input bound to 0.0.0.0 with no authentication in front of it.
GOOD: Bind to a specific interface where possible and flag any unauthenticated listener in the security audit.
References
scripts/
validate_config.py
- Main validation script with all checks integrated in a single file
- Usage:
python3 scripts/validate_config.py --file <config> --check <type> - Available check types:
all,structure,syntax,sections,tags,security,performance,best-practices,dry-run - Comprehensive 1000+ line validator covering all validation stages
- Returns detailed error messages with line numbers
- Supports JSON output format:
--json
validate.sh
- Convenience wrapper script for easier invocation
- Usage:
bash scripts/validate.sh <config-file> - Automatically calls validate_config.py with proper Python interpreter
Test Fixtures
The skill includes test configuration files in references/test-fixtures/ for validating the validator itself. See references/test-fixtures.md for details on running tests.
Documentation Sources
- Fluent Bit Official Documentation
- Fluent Bit Operations and Best Practices
- Configuration File Format
- Context7 Fluent Bit documentation (/fluent/fluent-bit-docs)
Quick Start
bash scripts/validate.sh <config-file>
python3 scripts/validate_config.py --file <config-file> --check all --json
fluent-bit -c <config-file> --dry-runExplicit NEVER/WHY/consequence triplets with side-by-side bad/good examples. Generic warnings score low — concrete failure modes with real impact (security, correctness, performance) score high.
Runtime validation via eval scenarios proving the skill actually changes agent behaviour. Requires evals/ directory, instructions.json, ≥3 scenarios, and ≥80% instruction coverage in summary.json.
Appropriate rigidity for the skill type: strict rules for critical/security skills, balanced steps for process skills, flexible options for tool skills. Mismatched calibration (too rigid or too loose) reduces score.
Expert-only knowledge the AI couldn't derive on its own — domain-specific patterns, production gotchas, decision frameworks, and non-obvious tool behaviour. High scores mean <5% redundancy with what the model already knows.
A clear philosophy plus numbered step-by-step workflows with explicit entry/exit points. Should answer: what is the core principle, how to execute it, and when (and when not) to apply it.
Rich activation keywords and trigger scenarios in the description so the skill fires when needed. Best descriptions read like an exhaustive list of the tasks and concepts that should invoke this skill.
Copy-paste-ready code, complete runnable examples, real file paths and commands. Pseudocode and abstract descriptions score low — concrete, executable content scores high.
SKILL.md as a <100-line navigation hub pointing to focused references/ files. Content should be lazy-loaded on demand, not front-loaded. Includes actionable 'When to Use' conditions per reference.
Proper frontmatter, single-task focus, activation keywords, and cross-harness portability. Skills must work across 40+ agentic harnesses without hardcoded paths or agent-specific references.
Expert-only knowledge the AI couldn't derive on its own — domain-specific patterns, production gotchas, decision frameworks, and non-obvious tool behaviour. High scores mean <5% redundancy with what the model already knows.
A clear philosophy plus numbered step-by-step workflows with explicit entry/exit points. Should answer: what is the core principle, how to execute it, and when (and when not) to apply it.
Explicit NEVER/WHY/consequence triplets with side-by-side bad/good examples. Generic warnings score low — concrete failure modes with real impact (security, correctness, performance) score high.
Proper frontmatter, single-task focus, activation keywords, and cross-harness portability. Skills must work across 40+ agentic harnesses without hardcoded paths or agent-specific references.
SKILL.md as a <100-line navigation hub pointing to focused references/ files. Content should be lazy-loaded on demand, not front-loaded. Includes actionable 'When to Use' conditions per reference.
Appropriate rigidity for the skill type: strict rules for critical/security skills, balanced steps for process skills, flexible options for tool skills. Mismatched calibration (too rigid or too loose) reduces score.
Rich activation keywords and trigger scenarios in the description so the skill fires when needed. Best descriptions read like an exhaustive list of the tasks and concepts that should invoke this skill.
Copy-paste-ready code, complete runnable examples, real file paths and commands. Pseudocode and abstract descriptions score low — concrete, executable content scores high.
No eval scenarios available.
Fluent Bit Configuration Section Validation Rules
This reference documents detailed validation rules and best practices for each Fluent Bit configuration section.
SERVICE Section
Required Fields
Flush- Required, must be numeric (recommended: 1-5 seconds)
Valid Fields
Log_Level- Must be one of:off,error,warn,info,debug,traceParsers_File- File path must exist if specifiedHTTP_Server- Boolean:OnorOffHTTP_Listen- IP address (default: 0.0.0.0)HTTP_Port- Port number (default: 2020)storage.metrics- Boolean:onoroffstorage.path- Directory path for bufferingstorage.sync- Sync mode:normalorfullstorage.checksum- Boolean:offoron
Best Practices
- Flush interval: 1-5 seconds for optimal performance
- HTTP Server: Enable with
HTTP_Server Onfor health checks and metrics - Storage metrics: Enable with
storage.metrics onfor monitoring buffer usage - Log level: Use
infofor production,debugonly for troubleshooting
INPUT Section
Required Fields
Name- Must be a valid plugin name (see Valid Plugins below)Tag- Must follow tag format (alphanumeric, dots, hyphens, wildcards)
Valid Plugins
tail- Read from log filesforward- Receive from Fluent Bit/Fluentdhttp- HTTP endpoint for log ingestiontcp- TCP listenersyslog- Syslog protocolsystemd- Systemd journalkubernetes_events- Kubernetes event stream
Plugin-Specific Validation
tail Plugin
Path- File path must exist (supports wildcards)Path_Key- Optional field name for file pathRead_from_Head- Boolean:OnorOffRefresh_Interval- Numeric (seconds)Rotate_Wait- Numeric (seconds)Skip_Long_Lines- Boolean:OnorOffSkip_Empty_Lines- Boolean:OnorOffDB- Database file for position trackingDB.locking- Boolean:trueorfalseMem_Buf_Limit- Memory limit (e.g.,5MB,100MB)Parser- Must reference existing parser
forward Plugin
Listen- IP address (default: 0.0.0.0)Port- Port number (default: 24224)Buffer_Size- Buffer size with unit (e.g.,32KB)
http Plugin
Listen- IP addressPort- Port numbertag_key- Optional tag field namesuccessful_response_code- HTTP response code (default: 200)
Best Practices
- Memory limits: Always set
Mem_Buf_Limit(50-100MB recommended) to prevent OOM - Position tracking: Use
DBparameter for tail inputs to survive restarts - Long lines: Set
Skip_Long_Lines Onto prevent memory issues - File rotation: Set
Refresh_Interval 10for rotated log detection - Empty lines: Set
Skip_Empty_Lines Onto reduce noise
FILTER Section
Required Fields
Name- Must be a valid filter plugin nameMatchorMatch_Regex- At least one required
Valid Plugins
parser- Parse unstructured logskubernetes- Enrich with Kubernetes metadatamodify- Add/remove/rename fieldsnest- Nest/lift nested fieldsgrep- Include/exclude recordsrecord_modifier- Modify record fieldsrewrite_tag- Re-emit with new tagthrottle- Rate limitingmultiline- Combine multiline logs
Common Fields
Match- Tag pattern (supports wildcards)Match_Regex- Regex pattern for tag matching
Plugin-Specific Validation
kubernetes Filter
Kube_URL- Kubernetes API URLKube_CA_File- CA certificate path (must exist)Kube_Token_File- Token file path (must exist)Kube_Tag_Prefix- Tag prefix (default:kube.)Merge_Log- Boolean:OnorOffKeep_Log- Boolean:OnorOffBuffer_Size- Recommend0(unbuffered) for performance
parser Filter
Key_Name- Field to parse (required)Parser- Parser name (must exist)Reserve_Data- Boolean:OnorOffPreserve_Key- Boolean:OnorOff
Best Practices
- Match patterns: Avoid bare
*unless intentional (matches everything) - Filter ordering: Place parsers before modifiers
- Kubernetes: Use
Buffer_Size 0for better performance - Field preservation: Use
Reserve_Data Onto keep original fields
OUTPUT Section
Required Fields
Name- Must be a valid output plugin nameMatch- Tag pattern to match
Valid Plugins
elasticsearch- Elasticsearch/OpenSearchopensearch- OpenSearch (dedicated plugin)kafka- Apache Kafkaloki- Grafana Lokis3- Amazon S3cloudwatch- Amazon CloudWatch Logshttp- Generic HTTP endpointforward- Forward to Fluent Bit/Fluentdfile- Write to filestdout- Write to stdoutopentelemetry- OpenTelemetry protocolsplunk- Splunk HECdatadog- Datadog
Common Fields
Match- Tag pattern (required)Retry_Limit- Number of retries (recommended: 3-5)storage.total_limit_size- Total buffer size (e.g.,5G)tls- Boolean:onorofftls.verify- Boolean:onorofftls.ca_file- CA certificate pathtls.crt_file- Client certificate pathtls.key_file- Client key pathCompress- Compression algorithm:gzip
Plugin-Specific Validation
elasticsearch/opensearch Plugin
Host- Hostname or IP (required)Port- Port number (default: 9200)Index- Index nameType- Document type (deprecated in ES 7+)Logstash_Format- Boolean:OnorOffLogstash_Prefix- Index prefix (default:logstash)HTTP_User- Username (use env var)HTTP_Passwd- Password (use env var)Suppress_Type_Name- Boolean:OnorOff(required for ES 7+)
opentelemetry Plugin
Host- Hostname or IP (required)Port- Port numbermetrics_uri- Metrics endpoint (e.g.,/v1/metrics)logs_uri- Logs endpoint (e.g.,/v1/logs)traces_uri- Traces endpoint (e.g.,/v1/traces)header- Custom headers (can specify multiple)
kafka Plugin
Brokers- Comma-separated broker list (required)Topics- Topic name (required)Format- Message format:json,msgpack,gelfMessage_Key- Optional partition key fieldrdkafka.*- librdkafka configuration options
Best Practices
- Retry configuration: Set
Retry_Limit 3-5to handle transient failures - Storage limits: Configure
storage.total_limit_sizeto prevent disk exhaustion - TLS: Enable TLS in production with
tls onandtls.verify on - Credentials: Use environment variables instead of hardcoded credentials
- Compression: Enable
Compress gzipfor network outputs to reduce bandwidth - Elasticsearch: Set
Suppress_Type_Name Onfor Elasticsearch 7.x and newer
PARSER Section
Required Fields
Name- Parser name (unique identifier)Format- Parser format type (see Valid Formats)
Valid Formats
json- JSON parserregex- Regular expression parserlogfmt- Logfmt parserltsv- LTSV (Labeled Tab-Separated Values) parser
Format-Specific Fields
json Format
Time_Key- Field containing timestampTime_Format- strptime format stringTime_Keep- Boolean:OnorOff
regex Format
Regex- Regular expression with named capture groups (required)Time_Key- Field containing timestampTime_Format- strptime format stringTime_Keep- Boolean:OnorOffTypes- Type conversion (e.g.,status:integer)
logfmt Format
No additional required fields, but supports:
Time_Key- Field containing timestampTime_Format- strptime format string
Validation Rules
- Regex syntax: Must be valid POSIX ERE (Extended Regular Expression)
- Time format:
Time_FormatrequiresTime_Keyto be set - Named groups: Regex must use named capture groups:
(?<field_name>pattern)
Best Practices
- Built-in parsers: Use built-in parsers when possible (docker, apache, nginx, syslog)
- Multiline logs: Use
MULTILINE_PARSERsection for stack traces and multiline formats - Type conversion: Use
Typesparameter to convert strings to integers/floats - Time parsing: Always set
Time_KeyandTime_Formatfor proper timestamp handling - Testing: Test regex patterns with sample logs before deployment
Common Validation Errors
Structure Errors
- Missing section header:
[SECTION_NAME]required before key-value pairs - Invalid key-value format: Must be
Key Value(space-separated) - Unclosed brackets: Check for matching
[and] - Mixed indentation: Use consistent spaces (not tabs)
Section Errors
- Invalid plugin name: Check spelling against valid plugin lists above
- Missing required field: Each section type has required fields
- Invalid field value: Check against allowed values for each field
Tag Errors
- Unmatched tags: FILTER/OUTPUT Match patterns must correspond to INPUT tags
- Orphaned filters: FILTER without matching INPUT or OUTPUT
- Wildcard issues: Ensure wildcard patterns match intended tags
Security Errors
- Hardcoded credentials: Never hardcode passwords, API keys, or tokens
- TLS disabled: Always enable TLS in production
- Insecure verify: Avoid
tls.verify Offin production - World-readable secrets: Check file permissions on DB files and certificates
Performance Issues
- Missing memory limits: Always set
Mem_Buf_Limiton tail inputs - No storage limits: Set
storage.total_limit_sizeon outputs - Long flush intervals: Keep Flush at 1-5 seconds
- No compression: Enable compression on network outputs
Test Configuration Files
This directory contains test fixtures for validating the Fluent Bit configuration validator.
Test Files
Valid Configurations:
valid-basic.conf- Valid basic Kubernetes logging setupvalid-multioutput.conf- Valid configuration with multiple outputsvalid-opentelemetry.conf- Valid OpenTelemetry output configuration (Fluent Bit 2.x+)
Invalid Configurations:
invalid-missing-required.conf- Missing required parametersinvalid-security-issues.conf- Security vulnerabilities (hardcoded credentials, disabled TLS)invalid-opentelemetry.conf- OpenTelemetry configuration errorsinvalid-tag-mismatch.conf- Tag routing issues
Running Tests
Test Individual Config
# Test on valid config
python3 scripts/validate_config.py --file references/test-fixtures/valid-basic.conf
# Test on invalid config (should report errors)
python3 scripts/validate_config.py --file references/test-fixtures/invalid-security-issues.conf
Test All Configs
for config in references/test-fixtures/*.conf; do
echo "Testing $config"
python3 scripts/validate_config.py --file "$config"
done
Expected Results
Valid configurations should pass all validation checks. Invalid configurations should report specific errors matching their intended failure scenarios.