vlucas/phpdotenv · critical · ValidationException
One or more environment variables failed assertions: %s.
Error message
One or more environment variables failed assertions: %s.
What it means
Validator::assert() (src/Validator.php:173) is the funnel behind required(), notEmpty(), isInteger(), isBoolean(), allowedValues(), allowedRegexValues() and custom assertions: it evaluates a callback per variable against the repository and, if any returned false, aggregates 'VAR <reason>' fragments (e.g. 'DB_HOST is missing', 'PORT is not an integer') and throws Dotenv\Exception\ValidationException. One exception therefore reports every failing variable at once. required() itself is just assert(fn ($v) => $v !== null, 'is missing'), and assertNullable-based checks skip variables whose value is null.
Source
Thrown at src/Validator.php:173
* @param callable(?string):bool $callback
* @param string $message
*
* @throws \Dotenv\Exception\ValidationException
*
* @return \Dotenv\Validator
*/
public function assert(callable $callback, string $message)
{
$failing = [];
foreach ($this->variables as $variable) {
if ($callback($this->repository->get($variable)) === false) {
$failing[] = \sprintf('%s %s', $variable, $message);
}
}
if (\count($failing) > 0) {
throw new ValidationException(\sprintf(
'One or more environment variables failed assertions: %s.',
\implode(', ', $failing)
));
}
return $this;
}
/**
* Assert that the callback returns true for each variable.
*
* Skip checking null variable values.
*
* @param callable(string):bool $callback
* @param string $message
*
* @throws \Dotenv\Exception\ValidationException
*View on GitHub (pinned to 416df70283)
Solutions
- Read the message — it lists each failing variable with its reason; fix those entries in .env or the real environment first.
- Check spelling of the variable names in required([...]) against the .env keys.
- Make optional variables non-fatal with ifPresent([...])->notEmpty() instead of required(...).
- Allow empty values where legitimate: stop at ->required() and drop ->notEmpty().
- For guided setup, catch the exception and print 'copy .env.example to .env and fill it in', exiting non-zero.
Example fix
// before $dotenv->required(['APP_KEY', 'DB_HOST', 'MAIL_FROM'])->notEmpty(); // after $dotenv->required(['APP_KEY', 'DB_HOST'])->notEmpty(); // hard dependencies $dotenv->ifPresent(['MAIL_FROM'])->notEmpty(); // optional but must not be blank when set
Defensive patterns
Strategy: try-catch
Validate before calling
// Quick pre-boot presence check for hard dependencies (mirrors required()):
$required = ['APP_KEY', 'DB_HOST'];
$missing = array_filter(
$required,
static fn (string $name): bool => $_ENV[$name] ?? getenv($name) === false
);
if ($missing !== []) {
fwrite(STDERR, 'Missing env vars: ' . implode(', ', $missing) . \PHP_EOL);
exit(1);
} Try / catch
use Dotenv\Exception\ValidationException;
try {
$dotenv->required(['APP_KEY', 'DB_HOST'])->notEmpty();
} catch (ValidationException $e) {
// message already lists every failing var and reason, e.g.
// 'One or more environment variables failed assertions: APP_KEY is missing, DB_HOST is empty.'
fwrite(STDERR, $e->getMessage() . \PHP_EOL . 'Hint: copy .env.example to .env and fill it in.' . \PHP_EOL);
exit(1); // fail the boot/deploy instead of running half-configured
} Prevention
- Keep .env.example as the source of truth and diff it against .env in CI.
- Prefer ifPresent() for optional variables so absent values do not kill boot.
- Run the full required()/notEmpty() chain in a deploy smoke test before traffic switches.
- Watch for required()-list typos — a misspelled name reports as 'is missing' even though the real var is set.
When it happens
Trigger: Dotenv::createImmutable($dir)->load()->required('DB_HOST') when DB_HOST is absent (-> 'DB_HOST is missing'); ->required('APP_KEY')->notEmpty() when APP_KEY is unset, '' or whitespace-only (notEmpty trims before checking); ->required('PORT')->isInteger() with PORT=8080.5; allowedValues(['staging','prod']) with APP_ENV=dev; calling ->required() after safeLoad() when no file was read at all.
Common situations: New deploy/container missing secrets; fresh clone without .env; typo in the required() list ('DB_H0ST'); vars defined in .env but a different file was loaded (wrong path/name); whitespace-only values from a template; CI runners lacking environment configuration.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Expected name to be a non-empty string.
- At least one environment file path must be provided.
- Failed to parse dotenv file. %s
- Expected either an instance of %s or a class-string implemen
- Illegal character encoding [%s] specified.
AI-assisted analysis of vlucas/phpdotenv@416df70283 (2026-08-21).
Data as JSON: /api/errors/3ccb52a997052564.
Report an issue: GitHub.