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

  1. 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.
  2. 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.
  3. 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.
  4. 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

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


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/25ee3b0961db94ff. Report an issue: GitHub.