docker/compose · error

unknown copy direction

Error message

unknown copy direction

What it means

The copy direction is derived from service prefixes: a prefix on Source sets fromService, a prefix on Destination sets toService. If neither argument has a SERVICE: prefix, direction stays 0 and Compose cannot identify any container to talk to, so it fails fast with 'unknown copy direction'. Host-to-host copying is not something compose cp does.

Source

Thrown at pkg/compose/cp.go:74

	var direction copyDirection
	var serviceName string
	var copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error
	if srcService != "" {
		direction |= fromService
		serviceName = srcService
		copyFunc = s.copyFromContainer
	}
	if destService != "" {
		direction |= toService
		serviceName = destService
		copyFunc = s.copyToContainer
	}
	if direction == acrossServices {
		return errors.New("copying between services is not supported")
	}

	if direction == 0 {
		return errors.New("unknown copy direction")
	}

	containers, err := s.listContainersTargetedForCopy(ctx, projectName, options, direction, serviceName)
	if err != nil {
		return err
	}

	g := errgroup.Group{}
	for _, cont := range containers {
		ctr := cont
		g.Go(func() error {
			name := getCanonicalContainerName(ctr)
			var msg string
			if direction == fromService {
				msg = fmt.Sprintf("%s:%s to %s", name, srcPath, dstPath)
			} else {
				msg = fmt.Sprintf("%s to %s:%s", srcPath, name, dstPath)
			}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Prefix exactly one side with the service name: `docker compose cp ./file.txt web:/app/file.txt`
  2. If you genuinely want host-to-host copies, use plain `cp`/`rsync` — compose cp always involves containers
  3. Check shell variables used in the command (e.g. `echo "$svc:/path"`) to ensure the service name is not empty
  4. Verify the service exists with `docker compose ps` so the prefix matches a running service

Example fix

# before
docker compose cp ./app.conf "${SVC:-}:/etc/app.conf"
# after
SVC=web docker compose cp ./app.conf "${SVC}:/etc/app.conf"
Defensive patterns

Strategy: validation

Validate before calling

# ensure at least one side carries a service prefix and the variable is set
: "${SVC:?SVC must be set}"
[ -n "${SVC}" ] && docker compose cp ./file "${SVC}:/path"

Prevention

When it happens

Trigger: Running `docker compose cp ./file.txt ./other.txt` or api.Copy with options.Source and options.Destination that both lack the `service:` prefix after splitCpArg.

Common situations: Typos where the colon is dropped (`docker compose cp data.json web:/app` vs `web /app`), shell variable expansion producing an empty service name (`$svc:/path` with svc unset), or misunderstanding compose cp as a generic file-copy tool between host paths.

Related errors


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