{"record":{"id":"33ef021411ec2cb3","repo":"docker/cli","slug":"invalid-argument-can-t-use-stdin-for-both-build-c","errorCode":null,"errorMessage":"invalid argument: can't use stdin for both build context and dockerfile","messagePattern":"invalid argument: can't use stdin for both build context and dockerfile","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/image/build.go","lineNumber":210,"sourceCode":"\t\tbuildBuff     io.Writer\n\t\tremote        string\n\t)\n\n\tif options.platform != \"\" {\n\t\t_, err := platforms.Parse(options.platform)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tcontextType, err := build.DetectContextType(options.context)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif options.dockerfileFromStdin() {\n\t\tif contextType == build.ContextTypeStdin {\n\t\t\treturn errors.New(\"invalid argument: can't use stdin for both build context and dockerfile\")\n\t\t}\n\t\tdockerfileCtx = dockerCli.In()\n\t}\n\n\tprogBuff = dockerCli.Out()\n\tbuildBuff = dockerCli.Out()\n\tif options.quiet {\n\t\tprogBuff = bytes.NewBuffer(nil)\n\t\tbuildBuff = bytes.NewBuffer(nil)\n\t}\n\tif options.imageIDFile != \"\" {\n\t\t// Avoid leaving a stale file if we eventually fail\n\t\tif err := os.Remove(options.imageIDFile); err != nil && !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"removing image ID file: %w\", err)\n\t\t}\n\t}\n\n\tswitch contextType {","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/image/build.go#L192-L228","documentation":"runBuild() detects when the Dockerfile is to be read from stdin (dockerfileName == \"-\", i.e. `-f -`). If the build context is ALSO sourced from stdin (DetectContextType returns ContextTypeStdin, i.e. context path is `-`), the single stdin stream cannot serve both, so the CLI rejects the combination up front.","triggerScenarios":"`docker build -f - -` (Dockerfile from stdin AND context from stdin), or piping only one stream while specifying `-` for both.","commonSituations":"Scripts that try to pipe a Dockerfile and a tarball simultaneously; confusion over which `-` means context vs Dockerfile.","solutions":["Put the Dockerfile inside the build context and pass a real context path","Provide the context as a tarball on stdin and a real `-f <path>` Dockerfile","Provide the Dockerfile on stdin (`-f -`) but give a directory path for the context"],"exampleFix":"// before\ndocker build -f - - < Dockerfile\n// after\necho 'FROM scratch' > Dockerfile && docker build -f Dockerfile .","handlingStrategy":"validation","validationCode":"dockerfileFromStdin := options.dockerfileName == \"-\"\ncontextType, _ := build.DetectContextType(options.context)\nif dockerfileFromStdin && contextType == build.ContextTypeStdin {\n    return errors.New(\"stdin cannot be used for both Dockerfile and build context\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never specify `-` for both `-f` and the context path","Embed the Dockerfile in the context directory and use a real `-f` path","When piping a tarball context, read the Dockerfile from within the tar, not stdin"],"tags":["build","cli","stdin-stdout"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}