Skip to content
Documentation

YAML Validation

Validate curl-runner YAML configuration files against the schema. Discover issues, get fix suggestions, and auto-fix common problems.

Feature overview →

Validate curl-runner YAML configuration files against the schema. Discover issues, get fix suggestions, and auto-fix common problems with a single command.

Overview

The curl-runner validate command provides comprehensive validation of your YAML configuration files. It checks structure, required fields, valid values, security issues, and common typos—with intelligent suggestions and auto-fix capabilities.

  • Schema Validation: Full curl-runner schema validation
  • Auto-Fix: Many issue types fix themselves with --fix
  • Typo Detection: Smart suggestions for misspellings
  • Security Checks: Detects hardcoded secrets & keys

Basic Usage

Run curl-runner validate to check your YAML files.

CLI Usage
# Validate all YAML files in current directory
curl-runner validate

# Validate specific file
curl-runner validate api.yaml

# Validate directory
curl-runner validate tests/

# Validate with glob pattern
curl-runner validate "tests/**/*.yaml"

CLI Options

  • -f, --fix: Automatically fix issues where possible. Fixes URL issues, method casing, header casing, and more.

  • -s, --strict: Treat warnings as errors. Useful for CI pipelines where you want stricter validation.

  • -q, --quiet: Only show files with issues. Valid files are not printed.

  • -h, --help: Show help message and exit.

Strict Mode
# Treat warnings as errors (for CI)
curl-runner validate --strict

# Short form
curl-runner validate -s

# Combine with quiet mode
curl-runner validate --strict --quiet

Auto-Fix

Use --fix to automatically fix common issues.

Auto-Fix Usage
# Validate and auto-fix issues
curl-runner validate --fix

# Short form
curl-runner validate -f

# Fix quietly (only show errors)
curl-runner validate -fq

# Fix specific files
curl-runner validate api.yaml --fix

Auto-Fixable Issues

  • Lowercase HTTP methods → UPPERCASE
  • Missing https:// prefix
  • Protocol typos (htps, htpp, etc.)
  • Hostname typos (locahost, etc.)
  • Double slashes in URL paths
  • Spaces in URLs → %20
  • Header casing (content-type → Content-Type)
  • Lowercase execution mode
  • Lowercase output format
  • Lowercase prettyLevel

Manual Fix Required

  • Invalid auth types
  • Missing required fields (url)
  • Invalid status codes
  • Schema conflicts (body + formData)
  • Unknown keys with no suggestion
  • Invalid port numbers
  • Hardcoded credentials
  • Invalid JSON body

Output Examples

The validate command provides clear, colorized output showing what passed, what failed, and the severity of each issue.

Validation Output
curl-runner validate

Files: 5 found

✓ api/invalid.yaml
  ● request.url: URL should start with http:// or https://
    fix: Prepend https://
  ● request.method: Method should be uppercase: "GET"
    fix: Change to "GET"
  ● request.headers.content-type: Header "content-type" should be "Content-Type" for consistency
    fix: Rename to "Content-Type"
  ● request.insecure: Insecure mode disables SSL verification
  → 3 warning(s), 1 info

✓ api/orders.yaml
✓ api/posts.yaml
✓ api/products.yaml
✓ api/users.yaml

All files valid!

Files with warnings still count as valid. With --strict they fail:

Output with --strict
curl-runner validate --strict -q

Files: 5 found

✗ api/invalid.yaml
  ● request.insecure: Insecure mode disables SSL verification
  → 1 warning(s)

Summary: 1 file(s) with 1 issue(s)

With auto-fix enabled:

Output with --fix
curl-runner validate --fix

Files: 5 found

✓ api/invalid.yaml
  ● request.url: URL should start with http:// or https://
  ● request.method: Method should be uppercase: "GET"
  ● request.headers.content-type: Header "content-type" should be "Content-Type" for consistency
  ● request.insecure: Insecure mode disables SSL verification
  ✓ Fixed 3 issue(s)
  → 3 warning(s), 1 info

✓ api/orders.yaml
✓ api/posts.yaml
✓ api/products.yaml
✓ api/users.yaml

All files valid!

Auto-fix rewrites the file

--fix writes the file back in place and re-serializes the YAML, so formatting and comments are not preserved. Review the diff before committing.

URL Validations

Comprehensive URL validation with typo detection and auto-fix capabilities.

missing-protocol.yaml
# URL Validations

# Missing protocol (warning, auto-fixable)
request:
  url: api.example.com/users
Output
$ curl-runner validate missing-protocol.yaml
✓ missing-protocol.yaml
  ● request.url: URL should start with http:// or https://
    fix: Prepend https://
  → 1 warning(s)
All files valid!
protocol-typo.yaml
# Protocol typo (error, auto-fixable)
request:
  url: htps://api.example.com
Output
$ curl-runner validate protocol-typo.yaml
✗ protocol-typo.yaml
  ● request.url: URL contains typo "htps"
    fix: Fix to "https"
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
hostname-typo.yaml
# Hostname typo (error, auto-fixable)
request:
  url: https://locahost:3000/api
Output
$ curl-runner validate hostname-typo.yaml
✗ hostname-typo.yaml
  ● request.url: URL contains typo "locahost"
    fix: Fix to "localhost"
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
double-slash-in-path.yaml
# Double slash in path (warning, auto-fixable)
request:
  url: https://api.example.com//users
Output
$ curl-runner validate double-slash-in-path.yaml
✓ double-slash-in-path.yaml
  ● request.url: URL contains double slashes in path
    fix: Remove extra slashes
  → 1 warning(s)
All files valid!
spaces-in-url.yaml
# Spaces in URL (error, auto-fixable)
request:
  url: https://api.example.com/users /list
Output
$ curl-runner validate spaces-in-url.yaml
✗ spaces-in-url.yaml
  ● request.url: URL contains spaces
    fix: Encode spaces as %20
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
invalid-port.yaml
# Invalid port (error)
request:
  url: https://api.example.com:99999/api
Output
$ curl-runner validate invalid-port.yaml
✗ invalid-port.yaml
  ● request.url: Invalid port number 99999. Must be 1-65535
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
  • Detected URL Typos
    • htpp → http
    • htps → https
    • htp → http
    • httpss → https
    • locahost → localhost
    • localhsot → localhost
    • localhos → localhost
    • lcoalhost → localhost

Header Validations

Validates header names, detects duplicates, and checks Content-Type consistency.

wrong-casing.yaml
# Header Validations

# Wrong casing (info, auto-fixable)
request:
  url: https://api.example.com
  headers:
    content-type: application/json
    authorization: Bearer token
Output
$ curl-runner validate wrong-casing.yaml
✓ wrong-casing.yaml
  ● request.headers.content-type: Header "content-type" should be "Content-Type" for consistency
    fix: Rename to "Content-Type"
  ● request.headers.authorization: Header "authorization" should be "Authorization" for consistency
    fix: Rename to "Authorization"
  → 2 info
All files valid!
missing-content-type.yaml
# Missing Content-Type (info)
request:
  url: https://api.example.com
  method: POST
  body:
    name: test
Output
$ curl-runner validate missing-content-type.yaml
✓ missing-content-type.yaml
  ● request.headers: Body present but no Content-Type header; consider adding one
  → 1 info
All files valid!
duplicate-headers.yaml
# Duplicate headers (warning)
request:
  url: https://api.example.com
  headers:
    Content-Type: application/json
    content-type: text/plain
Output
$ curl-runner validate duplicate-headers.yaml
✓ duplicate-headers.yaml
  ● request.headers.content-type: Header "content-type" should be "Content-Type" for consistency
    fix: Rename to "Content-Type"
  ● request.headers.content-type: Duplicate header "content-type" (case-insensitive match with "Content-Type")
  → 1 warning(s), 1 info
All files valid!
  • Standard Header Casing
    • Content-Type
    • Authorization
    • Accept
    • Cache-Control
    • Content-Length
    • User-Agent
    • X-Requested-With
    • X-API-Key
    • Accept-Encoding

Security Validations

Detects potential security issues like hardcoded credentials and API keys.

hardcoded-credentials.yaml
# Security Validations

# Hardcoded credentials (warning)
request:
  url: https://api.example.com
  auth:
    type: basic
    username: admin
    password: secret123
Output
$ curl-runner validate hardcoded-credentials.yaml
✓ hardcoded-credentials.yaml
  ● request.auth.password: Hardcoded password. Consider using "${env.PASSWORD}"
  → 1 warning(s)
All files valid!
jwt-in-header.yaml
# JWT in header (warning)
request:
  url: https://api.example.com
  headers:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature
Output
$ curl-runner validate jwt-in-header.yaml
✓ jwt-in-header.yaml
  ● request.headers.Authorization: Potentially sensitive header value. Consider using variables like "${env.TOKEN}"
  → 1 warning(s)
All files valid!
api-key-patterns.yaml
# API key patterns (warning)
request:
  url: https://api.example.com
  headers:
    X-API-Key: sk-live-xxxxxxxxxxxxx
Output
$ curl-runner validate api-key-patterns.yaml
✓ api-key-patterns.yaml
  ● request.headers.X-API-Key: Potentially sensitive header value. Consider using variables like "${env.TOKEN}"
  → 1 warning(s)
All files valid!
insecure-mode.yaml
# Insecure mode (warning)
request:
  url: https://api.example.com
  insecure: true
Output
$ curl-runner validate insecure-mode.yaml
✓ insecure-mode.yaml
  ● request.insecure: Insecure mode disables SSL verification
  → 1 warning(s)
All files valid!

Detected Patterns

  • JWT tokens (Bearer eyJ...)
  • Stripe API keys (sk_live_, sk_test_)
  • AWS access keys (AKIA...)
  • Common password field names (password, passwd, secret, api_key, etc.)
  • Hardcoded bearer tokens
  • Insecure SSL mode

Unknown Key Detection

Detects unknown configuration keys and suggests corrections using edit distance matching.

typo-in-key-name.yaml
# Unknown Key Detection with Suggestions

# Typo in key name
request:
  url: https://api.example.com
  methood: GET
Output
$ curl-runner validate typo-in-key-name.yaml
✓ typo-in-key-name.yaml
  ● request.methood: Unknown key "methood" (did you mean "method"?)
    fix: Rename to "method"
  → 1 warning(s)
All files valid!
The YAML editor with the key backof underlined as a warning. A popover reads: Unknown key backof (did you mean backoff?) and offers the quick fix Rename to "backoff". The Problems panel lists the same warning at line 13.
In the editor, the same check underlines the unknown key as you type and offers the rename as a quick fix. Shown in curl-runner studio, a macOS preview.
typo-in-nested-key.yaml
# Typo in nested key
request:
  url: https://api.example.com
  auth:
    tpye: bearer
    token: ${TOKEN}
Output
$ curl-runner validate typo-in-nested-key.yaml
✗ typo-in-nested-key.yaml
  ● request.auth.tpye: Unknown key "tpye" (did you mean "type"?)
    fix: Rename to "type"
  ● request.auth.type: Auth type is required
  → 1 error(s), 1 warning(s)
Summary: 1 file(s) with 2 issue(s)
global-config-typo.yaml
# Global config typo
global:
  excution: parallel

requests:
  - url: https://api.example.com
Output
$ curl-runner validate global-config-typo.yaml
✓ global-config-typo.yaml
  ● global.excution: Unknown key "excution" (did you mean "execution"?)
    fix: Rename to "execution"
  → 1 warning(s)
All files valid!

What Gets Validated

The validator checks all aspects of your curl-runner configuration.

Structure

  • Must have request, requests, or collection
  • Unknown keys are flagged with suggestions
  • Valid YAML syntax
  • Duplicate request names detected

Request Fields

  • url - Required, validated format
  • method - GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
  • headers - Casing, duplicates
  • body - JSON validation, method compatibility

Authentication

  • auth.type - basic, bearer, digest, ntlm or oauth2
  • basic auth requires username
  • bearer auth requires token
  • Hardcoded credential detection

SSL/TLS Config

  • cert without key is flagged
  • key without cert is flagged
  • Path values must be strings
  • Insecure mode warning

Expect Assertions

  • Status codes must be 100-599
  • Response time format validation
  • Headers must be an object
  • Duration format (e.g., <500ms)

Global Config

  • execution: sequential or parallel
  • output.format: json, pretty, raw
  • output.prettyLevel: minimal, standard, detailed
  • ci.failOnPercentage: 0-100

Timeouts & Retries

  • timeout must be positive number
  • retry.count must be non-negative
  • retry.delay must be non-negative
  • retry.maxDelay must be non-negative

Proxy Config

  • proxy.url must be valid URL
  • proxy.auth requires username
  • Proxy URL protocol validation

Valid Configuration Examples

Here are examples of properly configured YAML files that pass validation.

Valid Request
# Valid request configuration
request:
  name: Get User
  url: https://api.example.com/users/1
  method: GET
  headers:
    Authorization: Bearer ${TOKEN}
    Content-Type: application/json
  timeout: 5000
  expect:
    status: 200
    headers:
      content-type: application/json
    body:
      id: 1

Global configuration:

Valid Global Config
# Valid global configuration
global:
  execution: parallel
  maxConcurrency: 5
  continueOnError: true
  output:
    format: pretty
    prettyLevel: detailed
  ci:
    strictExit: true
    failOn: 2

requests:
  - url: https://api.example.com/users
  - url: https://api.example.com/posts

Common Validation Errors

Here are examples of common validation errors and how to fix them.

missing-url.yaml
# Common validation errors

# Missing URL (error)
request:
  method: GET
Output
$ curl-runner validate missing-url.yaml
✗ missing-url.yaml
  ● request.url: URL is required
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
invalid-method.yaml
# Invalid method (error)
request:
  url: https://api.example.com
  method: INVALID
Output
$ curl-runner validate invalid-method.yaml
✗ invalid-method.yaml
  ● request.method: Invalid method "INVALID". Must be: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
lowercase-method.yaml
# Lowercase method (warning, auto-fixable)
request:
  url: https://api.example.com
  method: get
Output
$ curl-runner validate lowercase-method.yaml
✓ lowercase-method.yaml
  ● request.method: Method should be uppercase: "GET"
    fix: Change to "GET"
  → 1 warning(s)
All files valid!
invalid-auth-type.yaml
# Invalid auth type (error)
request:
  url: https://api.example.com
  auth:
    type: oauth
Output
$ curl-runner validate invalid-auth-type.yaml
✗ invalid-auth-type.yaml
  ● request.auth.type: Invalid auth type "oauth". Must be: basic, bearer, digest, ntlm, oauth2
    fix: Change to "oauth2"
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
invalid-status-code.yaml
# Invalid status code (error)
request:
  url: https://api.example.com
  expect:
    status: 1000
Output
$ curl-runner validate invalid-status-code.yaml
✗ invalid-status-code.yaml
  ● request.expect.status: Status code must be a number between 100-599
  → 1 error(s)
Summary: 1 file(s) with 1 issue(s)
body-and-formdata-conflict.yaml
# Body and formData conflict (error)
request:
  url: https://api.example.com
  body: { "test": "value" }
  formData:
    field: value
Output
$ curl-runner validate body-and-formdata-conflict.yaml
✗ body-and-formdata-conflict.yaml
  ● request.headers: Body present but no Content-Type header; consider adding one
  ● request: Cannot use both "body" and "formData"
  ● request.body: Body with GET method may be ignored by some servers
  → 1 error(s), 1 warning(s), 1 info
Summary: 1 file(s) with 3 issue(s)
body-with-get.yaml
# Body with GET (warning)
request:
  url: https://api.example.com
  method: GET
  body: { "test": "value" }
Output
$ curl-runner validate body-with-get.yaml
✓ body-with-get.yaml
  ● request.headers: Body present but no Content-Type header; consider adding one
  ● request.body: Body with GET method may be ignored by some servers
  → 1 warning(s), 1 info
All files valid!
duplicate-request-names.yaml
# Duplicate request names (warning)
requests:
  - name: GetUser
    url: https://api.example.com/users/1
  - name: GetUser
    url: https://api.example.com/users/2
Output
$ curl-runner validate duplicate-request-names.yaml
✓ duplicate-request-names.yaml
  ● requests[1]: Duplicate request name "GetUser" (also at requests[0])
  → 1 warning(s)
All files valid!

CI/CD Integration

Use validation in your CI/CD pipeline to catch configuration errors before deployment.

CI Integration
# GitHub Actions
- name: Validate YAML configs
  run: curl-runner validate tests/ --quiet

# GitLab CI (strict mode fails on warnings)
validate:
  script:
    - curl-runner validate tests/ --strict

# Pre-commit hook
curl-runner validate && curl-runner tests/

Exit Codes

  • 0 - All files valid (no errors)
  • 1 - One or more files have errors
  • 1 (with --strict) - Files have errors OR warnings

Best Practices

  • Recommended
    • Run validation before committing changes
    • Use --strict in CI pipelines
    • Use --quiet in automated scripts
    • Review auto-fixes before committing
    • Use environment variables for credentials
    • Validate entire test directories at once
  • Considerations
    • Auto-fix changes files in place
    • Some issues require manual intervention
    • Warnings don't fail validation (unless --strict)
    • Variables (${VAR}) are not resolved during validation
    • Security warnings suggest using env vars

Severity Levels

Each issue is printed with a colored ●; the color shows the severity and the summary line counts each level.

  • Error (red): Must be fixed. Fails validation.
  • Warning (yellow): Should be fixed. Often auto-fixable. Valid by default, fails with --strict.
  • Info (dim): For awareness. Does not affect the exit code.