{"record":{"id":"fcd06d8729370c2d","repo":"docker/compose","slug":"copying-between-services-is-not-supported","errorCode":null,"errorMessage":"copying between services is not supported","messagePattern":"copying between services is not supported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/cp.go","lineNumber":70,"sourceCode":"\tprojectName = strings.ToLower(projectName)\n\tsrcService, srcPath := splitCpArg(options.Source)\n\tdestService, dstPath := splitCpArg(options.Destination)\n\n\tvar direction copyDirection\n\tvar serviceName string\n\tvar copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error\n\tif srcService != \"\" {\n\t\tdirection |= fromService\n\t\tserviceName = srcService\n\t\tcopyFunc = s.copyFromContainer\n\t}\n\tif destService != \"\" {\n\t\tdirection |= toService\n\t\tserviceName = destService\n\t\tcopyFunc = s.copyToContainer\n\t}\n\tif direction == acrossServices {\n\t\treturn errors.New(\"copying between services is not supported\")\n\t}\n\n\tif direction == 0 {\n\t\treturn errors.New(\"unknown copy direction\")\n\t}\n\n\tcontainers, err := s.listContainersTargetedForCopy(ctx, projectName, options, direction, serviceName)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tg := errgroup.Group{}\n\tfor _, cont := range containers {\n\t\tctr := cont\n\t\tg.Go(func() error {\n\t\t\tname := getCanonicalContainerName(ctr)\n\t\t\tvar msg string\n\t\t\tif direction == fromService {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/cp.go#L52-L88","documentation":"The Compose copy API (docker compose cp) only supports copying between the host and containers of one service, in one direction. The source and destination arguments are parsed as SERVICE:PATH; when BOTH sides carry a service prefix, the direction bitmask becomes fromService|toService (acrossServices) and the copy is rejected before any container is contacted. This is an intentional limitation: Compose has no primitive to stream an archive directly between two service containers.","triggerScenarios":"Calling docker compose cp svc_a:/path svc_b:/path (or api.ComposeService.Copy with Source='svc_a:/file' and Destination='svc_b:/file'), i.e. both splitCpArg results yield a non-empty service name.","commonSituations":"Trying to move files between two services in one command (e.g. dumping a database from the db service into the app service), scripting backups where source and target are both containers, or assuming compose cp mirrors docker cp semantics (docker cp also cannot container->container, so users coming from scp expect it to work).","solutions":["Copy in two steps: `docker compose cp svc_a:/path ./tmpfile` then `docker compose cp ./tmpfile svc_b:/path`","If both services can share the file, mount the same volume or bind directory into both services and write to it instead of copying","Use `docker compose exec svc_a sh -c 'tar c ...' | docker compose exec -T svc_b tar x ...` for streaming pipelines in scripts","If you called the Go API, run two Copy calls (one fromService, one toService) with an intermediate host path"],"exampleFix":"# before\ndocker compose cp db:/dump.sql app:/dump.sql\n# after\ndocker compose cp db:/dump.sql ./dump.sql && docker compose cp ./dump.sql app:/dump.sql","handlingStrategy":"validation","validationCode":"# before calling compose cp, ensure exactly one side has a service prefix\ncp_args_check() {\n  case \"$1\" in *:*) src_svc=1;; *) src_svc=0;; esac\n  case \"$2\" in *:*) dst_svc=1;; *) dst_svc=0;; esac\n  [ $((src_svc + dst_svc)) -eq 1 ] || { echo \"need exactly one SERVICE: path\" >&2; return 2; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap compose cp in a script helper that rejects two-sided service:service arguments up front","Standardize on host-staging copies in pipelines rather than service-to-service assumptions"],"tags":["copy","cli","validation","compose-cp"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}