docker/compose · error

destination can not be empty

Error message

destination can not be empty

What it means

The counterpart of the source check: docker compose cp validates in PreRunE that args[1] — the destination, either DEST_PATH, '-', or SERVICE:DEST_PATH — is not the empty string. With cli.ExactArgs(2) already guaranteeing two positional args, this catches a present-but-empty second argument (quoted empty string) before runCopy executes.

Source

Thrown at cmd/compose/cp.go:56

	followLink  bool
	copyUIDGID  bool
}

func copyCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {
	opts := copyOptions{
		ProjectOptions: p,
	}
	copyCmd := &cobra.Command{
		Use: `cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-
	docker compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH`,
		Short: "Copy files/folders between a service container and the local filesystem",
		Args:  cli.ExactArgs(2),
		PreRunE: Adapt(func(ctx context.Context, args []string) error {
			if args[0] == "" {
				return errors.New("source can not be empty")
			}
			if args[1] == "" {
				return errors.New("destination can not be empty")
			}
			return nil
		}),
		RunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
			opts.source = args[0]
			opts.destination = args[1]
			return runCopy(ctx, dockerCli, backendOptions, opts)
		}),
		ValidArgsFunction: completeServiceNames(dockerCli, p),
	}

	flags := copyCmd.Flags()
	flags.IntVar(&opts.index, "index", 0, "Index of the container if service has multiple replicas")
	flags.BoolVar(&opts.all, "all", false, "Include containers created by the run command")
	flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH")
	flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)")

	return copyCmd

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Set the destination explicitly to a concrete path or '-', verifying the variable first: `: "${DEST:?destination required}"`.
  2. When piping to stdout, pass '-' as the destination instead of an empty string.
  3. Audit the surrounding script for misspelled or unexported variables feeding the cp command.

Example fix

# before
docker compose cp web:/app/log.txt "$DEST"
# DEST unset -> empty-string arg

# after
: "${DEST:?destination required}"
docker compose cp web:/app/log.txt "$DEST"
Defensive patterns

Strategy: validation

Validate before calling

: "${DEST:?docker compose cp needs a non-empty destination}"
docker compose cp "$SRC" "$DEST"

Prevention

When it happens

Trigger: Running `docker compose cp web:/app/log.txt ""`, or scripts where the destination variable is unset/empty but quoted so the shell still passes an empty argument, e.g. `docker compose cp src "$DEST"` with DEST unset.

Common situations: CI variables not exported into the job environment; typos in variable names (e.g. $DESTNATION); build scripts assuming a default output path that was never set.

Related errors


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