vlucas/phpdotenv · error · InvalidEncodingException
Conversion from encoding [%s] failed.
Error message
Conversion from encoding [%s] failed.
What it means
In Str::utf8() (src/Util/Str.php:49) mbstring's mb_convert_encoding() is run with error suppression; if it returns a non-string (false on failure), the Result becomes an error and Reader::readFromFile() throws Dotenv\Exception\InvalidEncodingException (src/Store/File/Reader.php:77). Unlike error [7] the encoding name was accepted — the conversion itself failed, meaning the file bytes could not be converted to UTF-8 under the declared (or auto-detected) encoding. The message prints 'NULL' when no encoding was given.
Source
Thrown at src/Store/File/Reader.php:77
/**
* Read the given file.
*
* @param string $path
* @param string|null $encoding
*
* @throws \Dotenv\Exception\InvalidEncodingException
*
* @return \PhpOption\Option<string>
*/
private static function readFromFile(string $path, ?string $encoding = null)
{
/** @var Option<string> */
$content = Option::fromValue(@\file_get_contents($path), false);
return $content->flatMap(static function (string $content) use ($encoding) {
return Str::utf8($content, $encoding)->mapError(static function (string $error) {
throw new InvalidEncodingException($error);
})->success();
});
}
}
View on GitHub (pinned to 416df70283)
Solutions
- Open the file in an editor, re-save it as plain UTF-8, and drop the fileEncoding argument (null auto-detect then works).
- If you keep a non-UTF-8 file, verify the declared encoding matches reality: mb_check_encoding(file_get_contents($path), $encoding).
- Inspect the first bytes (BOM) and file size — truncated multibyte files convert fine only after repair.
- Check for stray binary characters: bin2hex the region around any pasted secret.
Example fix
// before $dotenv = Dotenv::createImmutable(__DIR__, null, true, 'UTF-16')->load(); // file is actually UTF-8 -> InvalidEncodingException: Conversion from encoding [UTF-16] failed. // after (re-save .env as UTF-8, then) $dotenv = Dotenv::createImmutable(__DIR__)->load();
Defensive patterns
Strategy: validation
Validate before calling
// Prove the file converts cleanly before bootstrapping Dotenv:
$path = $dir . '/.env';
$content = file_get_contents($path);
if ($content !== false && $encoding !== null && !mb_check_encoding($content, $encoding)) {
throw new RuntimeException(".env is not valid {$encoding}; re-save it as UTF-8");
}
// For auto-detect (encoding === null), a round-trip sanity check:
if ($content !== false && @mb_convert_encoding($content, 'UTF-8') === false) {
throw new RuntimeException('.env content could not be converted to UTF-8');
} Try / catch
use Dotenv\Exception\InvalidEncodingException;
try {
Dotenv::createImmutable($dir, null, true, $encoding)->load();
} catch (InvalidEncodingException $e) {
// 'Conversion from encoding [X] failed.' -> the bytes do not match the declared encoding
// re-save the file as UTF-8 and retry once with encoding omitted; then fail hard
} Prevention
- Standardize all env files on UTF-8 and leave fileEncoding unset.
- Add a pre-commit/CI check that each .env passes mb_check_encoding in its declared encoding.
- Suspect truncated or binary-mangled content whenever a previously-working setup starts failing after tooling changes.
When it happens
Trigger: Declaring fileEncoding='UTF-16' while the file is actually UTF-8/corrupt/truncated (bad BOM, odd byte length); leaving encoding null so mb_convert_encoding auto-detection guesses wrong on mixed or binary content; a .env containing binary garbage or a truncated multibyte sequence; file mutated by a tool that mangled bytes.
Common situations: Files written by Windows editors claiming UTF-16 but saved differently; CI checkouts applying encoding-filters or CRLF manglers; secrets pasted from a password manager inserting odd bytes; partial uploads of the env file.
Related errors
- Illegal character encoding [%s] specified.
- Failed to parse dotenv file. %s
- At least one environment file path must be provided.
- Unable to read any of the environment file(s) at [%s].
- Expected name to be a non-empty string.
AI-assisted analysis of vlucas/phpdotenv@416df70283 (2026-08-21).
Data as JSON: /api/errors/c4109fac9db3b91d.
Report an issue: GitHub.