{"record":{"id":"180b39e2a43bfcb8","repo":"docker/compose","slug":"source-can-not-be-empty","errorCode":null,"errorMessage":"source can not be empty","messagePattern":"source can not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/compose/cp.go","lineNumber":53,"sourceCode":"\tdestination string\n\tindex       int\n\tall         bool\n\tfollowLink  bool\n\tcopyUIDGID  bool\n}\n\nfunc copyCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {\n\topts := copyOptions{\n\t\tProjectOptions: p,\n\t}\n\tcopyCmd := &cobra.Command{\n\t\tUse: `cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-\n\tdocker compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH`,\n\t\tShort: \"Copy files/folders between a service container and the local filesystem\",\n\t\tArgs:  cli.ExactArgs(2),\n\t\tPreRunE: Adapt(func(ctx context.Context, args []string) error {\n\t\t\tif args[0] == \"\" {\n\t\t\t\treturn errors.New(\"source can not be empty\")\n\t\t\t}\n\t\t\tif args[1] == \"\" {\n\t\t\t\treturn errors.New(\"destination can not be empty\")\n\t\t\t}\n\t\t\treturn nil\n\t\t}),\n\t\tRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {\n\t\t\topts.source = args[0]\n\t\t\topts.destination = args[1]\n\t\t\treturn runCopy(ctx, dockerCli, backendOptions, opts)\n\t\t}),\n\t\tValidArgsFunction: completeServiceNames(dockerCli, p),\n\t}\n\n\tflags := copyCmd.Flags()\n\tflags.IntVar(&opts.index, \"index\", 0, \"Index of the container if service has multiple replicas\")\n\tflags.BoolVar(&opts.all, \"all\", false, \"Include containers created by the run command\")\n\tflags.BoolVarP(&opts.followLink, \"follow-link\", \"L\", false, \"Always follow symbol link in SRC_PATH\")","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/cmd/compose/cp.go#L35-L71","documentation":"docker compose cp requires exactly two non-empty positional arguments (enforced by cli.ExactArgs(2) plus a PreRunE check). The PreRunE in cmd/compose/cp.go validates that args[0] — the source, either SERVICE:SRC_PATH or a local SRC_PATH / '-' for stdin — is not the empty string. An empty first argument passes cobra's arg-count check but fails this guard before any container operation starts.","triggerScenarios":"Running `docker compose cp \"\" dest`, `docker compose cp \"\" container:/path`, or a script where the source variable expands to empty (e.g. unset $SRC), because shell word-splitting still yields an empty-string argument when quoted.","commonSituations":"Shell scripts with unset or misnamed source variables; YAML/CI pipelines interpolating an empty value into the cp arguments; copying from stdin ('-') but accidentally quoting an empty variable instead.","solutions":["Fix the source argument: verify the variable is set and non-empty before invoking cp (e.g. : \"${SRC:?source path required}\").","If copying from stdin, use the literal '-' as the source argument.","Double-check the SERVICE:SRC_PATH syntax — the service name and path must both be present on the container side."],"exampleFix":"# before\ndocker compose cp \"$SRC\" web:/app\n# $SRC unset -> empty-string arg\n\n# after\n: \"${SRC:?source path required}\"\ndocker compose cp \"$SRC\" web:/app","handlingStrategy":"validation","validationCode":": \"${SRC:?docker compose cp needs a non-empty source}\"\ndocker compose cp \"$SRC\" \"${DEST:?}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use ${VAR:?message} guards for every interpolated cp argument.","Use the literal '-' when streaming from stdin."],"tags":["cli","cp","validation","arguments"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}