A pre-deployment environment validation tool. Validates type correctness, required presence, and environment-specific rules before your application starts — not after it crashes.
Most .env loaders (dotenv, python-dotenv) only check if the file exists and load its values into the process. They do not validate those values. Common failures that reach production:
PORT=banana— present, but not a valid integerDATABASE_URL=— present, but emptyAPI_KEY=undefined— present, but a literal string "undefined"
These pass a presence check. They fail at runtime — usually deep inside application logic, far from where the bad config was loaded.
env-check validates before execution. If your config is broken, your app refuses to start. The error is explicit, structured, and caught at startup — not in production.
| Feature | env-check | dotenv | envalid | python-dotenv |
|---|---|---|---|---|
| Philosophy | Gatekeeper | Loader | Validator | Loader |
| Type enforcement | Yes | No | Yes | No |
| Empty value detection | Yes | No | Partial | No |
| Environment-specific rules | Yes | No | Partial | No |
| CI/CD-friendly output | JSON + exit code | Noisy | Partial | Silent errors |
| Auto-loads env into app | No (by design) | Yes | Yes | Yes |
env-check does not load your environment. It validates it. You handle loading separately — this keeps the tool composable and safe for pipelines.
pip install env-checkRequirements: Python 3.8+
1. Define a schema
// env.schema.json
{
"PORT": {
"type": "integer",
"required": true,
"range": [1024, 65535]
},
"DATABASE_URL": {
"type": "url",
"required": true,
"environments": ["production", "staging"]
},
"DEBUG": {
"type": "boolean",
"default": false
},
"API_KEY": {
"type": "string",
"required": true,
"disallow": ["undefined", "null", ""]
}
}2. Run validation in your app entrypoint
from env_check import EnvGuard
guard = EnvGuard(schema="env.schema.json")
guard.protect() # Raises EnvValidationError if config is invalid. App exits here.
# Your application logic starts only after this point.3. Or run from the CLI
env-check --schema env.schema.json --env productionUsage: env-check [OPTIONS]
Options:
--schema PATH Path to the schema file (JSON or YAML). [required]
--file PATH Path to the .env file. Defaults to .env
--env TEXT Environment name (e.g. production, staging, dev)
--output [json|text] Output format. Defaults to text
--strict Fail on any unknown keys not defined in schema
--help Show this message and exit.
Exit codes:
0— All validations passed1— One or more validations failed2— Schema or config file not found
JSON output example (for CI pipelines):
{
"status": "failed",
"errors": [
{ "key": "PORT", "error": "Expected integer, got 'banana'" },
{ "key": "API_KEY", "error": "Value is disallowed: 'undefined'" }
]
}| Parameter | Type | Description |
|---|---|---|
schema |
str |
Path to your schema file (JSON or YAML) |
env_file |
str |
Path to the .env file. Defaults to .env |
environment |
str |
Current environment name for env-specific rules |
strict |
bool |
Fail on keys present in .env but not in schema |
Runs validation. Raises EnvValidationError with a detailed report if any rule fails. Does not return a value — either passes or halts execution.
Same as protect() but returns a result object instead of raising. Useful if you want to handle the error yourself.
result = guard.validate()
if not result.valid:
for error in result.errors:
print(error.key, error.message)| Rule | Types supported | Description |
|---|---|---|
type |
string, integer, float, boolean, url, email, json |
Enforces value type |
required |
All | Fails if key is missing or empty |
default |
All | Used when key is absent (only if not required) |
disallow |
string |
List of values that are explicitly rejected |
range |
integer, float |
[min, max] bounds check |
pattern |
string |
Regex the value must match |
environments |
All | Rule applies only to specified environments |
GitHub Actions example:
- name: Validate environment config
run: env-check --schema env.schema.json --env production --output jsonPipe the JSON output to any log aggregator or slack notifier. Exit code 1 will fail the pipeline automatically.
- Fork the repo
- Create a branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m "Add your feature" - Push and open a pull request
Please open an issue before submitting large changes.
MIT — see LICENSE for details.