vlucas/phpdotenv · error · InvalidFileException

Failed to parse dotenv file. %s

Error message

Failed to parse dotenv file. %s

What it means

Thrown as Dotenv\Exception\InvalidFileException by Parser::parse() (src/Parser/Parser.php:30) when the file content is not valid dotenv syntax. The parser splits content into lines (Lines::process drops comments/blank lines and stitches multiline quoted values), then runs each remaining entry through EntryParser inside a Result chain; the first Result error is rethrown with its concrete reason appended, e.g. 'Failed to parse dotenv file. Encountered an invalid name at [FOO BAR=1].'. This is the library's only syntax-error signal for ->load(), ->safeLoad() and Dotenv::parse().

Source

Thrown at src/Parser/Parser.php:30

final class Parser implements ParserInterface
{
    /**
     * Parse content into an entry array.
     *
     * @param string $content
     *
     * @throws \Dotenv\Exception\InvalidFileException
     *
     * @return \Dotenv\Parser\Entry[]
     */
    public function parse(string $content)
    {
        return Regex::split("/(\r\n|\n|\r)/", $content)->mapError(static function () {
            return 'Could not split into separate lines.';
        })->flatMap(static function (array $lines) {
            return self::process(Lines::process($lines));
        })->mapError(static function (string $error) {
            throw new InvalidFileException(\sprintf('Failed to parse dotenv file. %s', $error));
        })->success()->get();
    }

    /**
     * Convert the raw entries into proper entries.
     *
     * @param string[] $entries
     *
     * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[], string>
     */
    private static function process(array $entries)
    {
        /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[], string> */
        return \array_reduce($entries, static function (Result $result, string $raw) {
            return $result->flatMap(static function (array $entries) use ($raw) {
                return EntryParser::parse($raw)->map(static function (Entry $entry) use ($entries) {
                    /** @var \Dotenv\Parser\Entry[] */
                    return \array_merge($entries, [$entry]);

View on GitHub (pinned to 416df70283)

Solutions

  1. Read the text after 'Failed to parse dotenv file.' — it names the exact cause and the offending line (e.g. 'Encountered unexpected whitespace at [FOO=bar baz].').
  2. Double-quote values containing spaces, '#', '$' or quotes: FOO="bar baz".
  3. Fix or delete the named line; for multiline values make sure the opening " has a matching closing ".
  4. Inside double quotes only use escapes \n \r \t \v \f \" \\ \$; for literal text use single quotes (no escapes processed).
  5. Add a lint step to CI (e.g. dotenv-linter) and validate deployment artifacts with Dotenv::parse() before release.

Example fix

// before (.env)
APP_NAME=My App # comment
MAIL_DSN="smtp://user\q:pass@host"

// after (.env)
APP_NAME="My App" # comment
MAIL_DSN='smtp://user\q:pass@host'
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight a .env before wiring it into bootstrap (throws the same InvalidFileException on bad syntax):
use Dotenv\Dotenv;
use Dotenv\Exception\InvalidFileException;

try {
    Dotenv::parse((string) file_get_contents($dir . '/.env'));
} catch (InvalidFileException $e) {
    fwrite(STDERR, $e->getMessage() . \PHP_EOL); // names cause + offending line
    exit(1);
}

Try / catch

use Dotenv\Exception\InvalidFileException;
use Dotenv\Exception\InvalidPathException;
use Dotenv\Exception\InvalidEncodingException;

try {
    Dotenv::createImmutable($dir)->load();
} catch (InvalidFileException $e) {
    // syntax error: message contains the exact cause; fail the boot loudly
    throw new RuntimeException('Invalid .env syntax: ' . $e->getMessage(), 0, $e);
} catch (InvalidPathException | InvalidEncodingException $e) {
    // separate handling for path/encoding problems, see errors 7-10
}

Prevention

When it happens

Trigger: Calling Dotenv::createImmutable($dir)->load() or Dotenv::parse($content) with an entry that EntryParser rejects: a line starting with '=' ('=VALUE' -> 'an unexpected equals'); a name with characters outside [letters digits _ .] after export/quote stripping ('FOO BAR=1', 'FOO-BAR=1' -> 'an invalid name'); an unterminated quoted value ('FOO="bar' or "FOO='bar" -> 'a missing closing quote'); a double-quoted escape outside \\ \" \$ \f \n \r \t \v ('FOO="bar\q"' -> 'an unexpected escape sequence'); unquoted value with embedded whitespace followed by more text ('FOO=bar baz' -> 'unexpected whitespace'); or, rarely, a PCRE failure in the line split ('Could not split into separate lines.').

Common situations: Unquoted values containing spaces or inline '#' comments; secrets with quotes, backslashes or '$'; multiline blocks whose closing quote was deleted; keys with hyphens/spaces copied from docker-compose or shell scripts; hand-edited files pasted from chat/docs that mangled quotes; very large .env files hitting PCRE limits.

Understand the failure class

Related errors


AI-assisted analysis of vlucas/phpdotenv@416df70283 (2026-08-21). Data as JSON: /api/errors/8ba0d9046a74a0a2. Report an issue: GitHub.