docker/compose · error
failed to access env file %s: %w
Error message
failed to access env file %s: %w
What it means
Thrown while preparing a Compose application for publishing when os.Stat on a service's env_file fails with an error other than 'file does not exist' (for example EACCES or a path component that is not a directory). A missing optional env file is deliberately tolerated, but any other filesystem error aborts publishing because the tool cannot determine whether the file should be uploaded as part of the artifact.
Source
Thrown at pkg/compose/publish.go:263
}, func(options *loader.Options) {
options.SkipValidation = true
options.SkipExtends = true
options.SkipConsistencyCheck = true
options.ResolvePaths = true
options.SkipInclude = true
options.Profiles = project.Profiles
})
if err != nil {
return nil, err
}
for name, service := range base.Services {
for i, envFile := range service.EnvFiles {
// A real stat failure (e.g. permissions) is fatal, but a missing file is not:
// the project loader already rejects missing required env files before we get
// here, so an absent file at this point is an optional one.
_, statErr := os.Stat(envFile.Path)
if statErr != nil && !os.IsNotExist(statErr) {
return nil, fmt.Errorf("failed to access env file %s: %w", envFile.Path, statErr)
}
// The hash is derived from the path string alone, so the env_file is always
// rewritten to its opaque <hash>.env placeholder, even for a missing optional
// file, so the published artifact never leaks the local path. Only files that
// exist are registered for upload, mirroring the extends handling below.
hash := fmt.Sprintf("%x.env", sha256.Sum256([]byte(envFile.Path)))
if statErr == nil {
envFiles[envFile.Path] = hash
}
f, err = transform.ReplaceEnvFile(f, name, i, hash)
if err != nil {
return nil, err
}
}
if service.Extends == nil {
continue
}View on GitHub (pinned to ddc4b044b6)
Solutions
- Check the path and permissions of the env_file value reported in the message: ls -l and namei -l <path> to find the failing component.
- Grant read/execute on the file and every parent directory to the user running compose (chmod/chown), or move the env file to a readable location and update env_file.
- If the file is intentionally optional and genuinely absent, remove the stale path from env_file or mark it with required: false so the missing-file case is tolerated instead of surfacing a stat error.
- Fix ENOTDIR-style paths where a parent 'directory' is actually a file.
Example fix
# before (docker-compose.yml)
services:
api:
env_file:
- /secure/keys/.env # owned by root, mode 600
# after
services:
api:
env_file:
- ./.env # readable by the invoking user Defensive patterns
Strategy: validation
Validate before calling
func checkEnvFilesAccessible(project *types.Project) error {
for _, svc := range project.Services {
for _, ef := range svc.EnvFiles {
if _, err := os.Stat(ef.Path); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("env file %s not accessible: %w", ef.Path, err)
}
}
}
return nil
} Try / catch
if err := publishAPI(...); err != nil {
if strings.Contains(err.Error(), "failed to access env file") {
// surface the path from the message, check permissions, retry after fix
}
return err
} Prevention
- Run compose from a user that can read all referenced env files (verify with namei -l).
- Keep env files inside the project directory with standard 644 permissions.
- Lint compose files in CI for env_file paths that do not exist or are not readable.
When it happens
Trigger: Calling the publish API on a project whose service has env_file pointing to a path the current user cannot stat: permission denied on the file or a parent directory, or a path where an intermediate component is a regular file (ENOTDIR). Only non-ENOENT stat errors trigger it; absent optional files fall through.
Common situations: Running docker compose publish as a different user than the one owning the env file (common in CI with restrictive umasks), env_file under a directory with mode 700 owned by another user, or a typo that makes an intermediate path element a file instead of a directory.
Related errors
- cannot take exclusive lock for project %q: %w
- env file %s not found
- failed to scan env file %s: %w
- stat %q: %w
- inspecting %q: %w
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/25ee3b0961db94ff.
Report an issue: GitHub.