docker/compose · error

cannot create output folder: %w

Error message

cannot create output folder: %w

What it means

When bridge.Convert is called with opts.Output set, it first removes any existing directory at that path (os.RemoveAll) and then recreates it with os.MkdirAll(out, 0o744). This error means the recreation failed for a reason other than the directory already existing — the %w wraps the mkdir error. Typical causes are a parent that is not writable, a path component that is a file, or read-only filesystems.

Source

Thrown at pkg/bridge/convert.go:76

		return err
	}
	// for user to rely on compose.yaml attribute names, not go struct ones, we marshall back into YAML
	raw, err := project.MarshalYAML(types.WithSecretContent)
	// Marshall to YAML
	if err != nil {
		return fmt.Errorf("cannot render project into yaml: %w", err)
	}
	var model map[string]any
	err = yaml.Unmarshal(raw, &model)
	if err != nil {
		return fmt.Errorf("cannot render project into yaml: %w", err)
	}

	if opts.Output != "" {
		_ = os.RemoveAll(opts.Output)
		err := os.MkdirAll(opts.Output, 0o744)
		if err != nil && !os.IsExist(err) {
			return fmt.Errorf("cannot create output folder: %w", err)
		}
	}
	// Run Transformers images
	return convert(ctx, dockerCli, model, opts)
}

func convert(ctx context.Context, dockerCli command.Cli, model map[string]any, opts ConvertOptions) error {
	raw, err := yaml.Marshal(model)
	if err != nil {
		return err
	}

	dir, err := os.MkdirTemp("", "compose-convert-*")
	if err != nil {
		return err
	}
	defer func() {
		err := os.RemoveAll(dir)

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Check permissions on the parent directory and grant write access (chmod/chown) or choose a writable Output path
  2. Verify no regular file occupies the Output path or any parent component (ls -l on each segment)
  3. If Output is a bind mount, ensure it is mounted read-write
  4. Run the command with a fresh Output under a temp dir to confirm the rest of the conversion works

Example fix

# before
$ docker compose ... --output /opt/results
mkdir: permission denied
# after
$ sudo chown -R $(id -u) /opt/results  # or
$ docker compose ... --output ./results
Defensive patterns

Strategy: validation

Validate before calling

// Before Convert with Output set:
if opts.Output != "" {
	if err := os.MkdirAll(opts.Output, 0o744); err != nil {
		return fmt.Errorf("output path not writable: %w", err)
	}
	if info, err := os.Stat(opts.Output); err != nil || !info.IsDir() {
		return fmt.Errorf("output path %s is not a writable directory", opts.Output)
	}
}

Prevention

When it happens

Trigger: Calling bridge.Convert with Output pointing under a directory without write permission; Output whose parent path contains a regular file; Output on a read-only mount; a race where another process recreates the path as a file between RemoveAll and MkdirAll.

Common situations: CI containers running as a non-root user writing to /output or another root-owned path; converting to a path inside a read-only bind mount; a leftover file (not directory) at the Output path.

Related errors


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