docker/compose · error

failed to scan secret file

Error message

failed to scan secret file %s: %w

What it means

The pre-publish secret scan failed reading a top-level secret defined by file (secrets.<name>.file). Compose attempts to scan secret file contents like env and config files; a read failure aborts the publish.

Solutions

  1. Ensure the secret file exists at the referenced path and is readable by the user running compose publish.
  2. Add a CI step that materializes secret files (from the CI secret store) before publishing.
  3. Correct the path or use environment-based secrets (environment: key) instead of file-based ones when the file is not available at publish time.
  4. If secrets are external (driver-based), remove the file: reference so no local scan is required.

Example fix

# before
secrets:
  db-password:
    file: /run/secrets/db_password   # absent at publish time

# after
secrets:
  db-password:
    environment: DB_PASSWORD         # resolved from project environment
Defensive patterns

Strategy: validation

Validate before calling

func secretFilesReadable(project *types.Project) error {
	for name, sec := range project.Secrets {
		if sec.File == "" {
			continue
		}
		if fi, err := os.Stat(sec.File); err != nil || !fi.Mode().IsRegular() {
			return fmt.Errorf("secret %s file %q unreadable", name, sec.File)
		}
	}
	return nil
}

Try / catch

if err := publish(ctx, opts); err != nil {
    if strings.Contains(err.Error(), "failed to scan secret file") {
        // inject the secret file from the secret store, then retry
    }
    return err
}

Prevention

When it happens

Trigger: Publishing a project with a secrets: section whose file path cannot be read: missing-but-symlinked, directory instead of file, permission denied at read time, or I/O error.

Common situations: Secret files injected only at runtime (not present when publishing); paths pointing outside the repository; files owned by root in CI; rotated credentials files replaced mid-scan.

Related errors


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

Appendix: source

Thrown at pkg/compose/publish.go:739

	}

	// Check configs defined by files
	for _, config := range project.Configs {
		if config.File != "" {
			findings, err := scan.ScanFile(config.File)
			if err != nil {
				return nil, fmt.Errorf("failed to scan config file %s: %w", config.File, err)
			}
			allFindings = append(allFindings, findings...)
		}
	}

	// Check secrets defined by files
	for _, secret := range project.Secrets {
		if secret.File != "" {
			findings, err := scan.ScanFile(secret.File)
			if err != nil {
				return nil, fmt.Errorf("failed to scan secret file %s: %w", secret.File, err)
			}
			allFindings = append(allFindings, findings...)
		}
	}

	return allFindings, nil
}

func composeFileAsByteReader(ctx context.Context, filePath string, project *types.Project) (io.Reader, error) {
	base, err := loadUnresolvedFile(ctx, project, filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to load compose file %s: %w", filePath, err)
	}
	in, err := base.MarshalYAML()
	if err != nil {
		return nil, err
	}
	return bytes.NewBuffer(in), nil

View on GitHub (pinned to ddc4b044b6)