vlucas/phpdotenv · error · InvalidPathException

At least one environment file path must be provided.

Error message

At least one environment file path must be provided.

What it means

FileStore::read() (src/Store/FileStore.php:59) throws Dotenv\Exception\InvalidPathException when the store was constructed with an empty list of file paths — i.e. zero candidate directories/names were registered, so no read is even attempted. This is a configuration error, distinct from [10] where paths exist but no file could be read. Note safeLoad() catches InvalidPathException too, so it also swallows this case and returns [].

Source

Thrown at src/Store/FileStore.php:59

     */
    public function __construct(array $filePaths, bool $shortCircuit, ?string $fileEncoding = null)
    {
        $this->filePaths = $filePaths;
        $this->shortCircuit = $shortCircuit;
        $this->fileEncoding = $fileEncoding;
    }

    /**
     * Read the content of the environment file(s).
     *
     * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidPathException
     *
     * @return string
     */
    public function read()
    {
        if ($this->filePaths === []) {
            throw new InvalidPathException('At least one environment file path must be provided.');
        }

        $contents = Reader::read($this->filePaths, $this->shortCircuit, $this->fileEncoding);

        if (\count($contents) > 0) {
            return \implode("\n", $contents);
        }

        throw new InvalidPathException(
            \sprintf('Unable to read any of the environment file(s) at [%s].', \implode(', ', $this->filePaths))
        );
    }
}

View on GitHub (pinned to 416df70283)

Solutions

  1. Pass at least one directory: Dotenv::createImmutable(__DIR__)->load() (default name '.env' is appended).
  2. Guard dynamic lists: $paths = $computed ?: [__DIR__];
  3. If the env file is genuinely optional, call safeLoad() instead of load() — it suppresses this exception.
  4. Log count($paths) during boot to catch the misconfiguration early.

Example fix

// before
$dirs = glob(__DIR__.'/modules/*/.env', GLOB_ONLYDIR) ?: [];
Dotenv::createImmutable(array_map('dirname', $dirs))->load(); // empty on fresh clone -> throws

// after
$dirs = glob(__DIR__.'/modules/*/.env', GLOB_ONLYDIR) ?: [];
Dotenv::createImmutable(array_map('dirname', $dirs) ?: [__DIR__])->safeLoad();
Defensive patterns

Strategy: validation

Validate before calling

// Never hand Dotenv an empty path list:
$paths = array_filter(
    array_map('strval', (array) ($config['env_dirs'] ?? [])),
    static fn (string $p) => trim($p, '/ ') !== ''
);
if ($paths === []) {
    $paths = [dirname(__DIR__)]; // sane fallback: project root
}
Dotenv::createImmutable($paths)->safeLoad();

Type guard

function hasEnvPaths(array $paths): bool
{
    return count(array_filter($paths, 'is_string')) > 0;
}

Prevention

When it happens

Trigger: Dotenv::createImmutable([])->load() or Dotenv::create($repo, [])->load(); a StoreBuilder built with createWithDefaultName() but no addPath() call; paths computed dynamically from glob()/scandir()/config that returned an empty array before create() was called.

Common situations: Config-driven env directories ('env_paths' key empty in a bundle config); glob() matching nothing because the cwd differs from the project root; refactoring that moved the path list construction and silently dropped it.

Related errors


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