{"record":{"id":"d14dcf7a64a9e6c6","repo":"docker/cli","slug":"valid-streams-are-stdin-stdout-and-stderr","errorCode":null,"errorMessage":"valid streams are STDIN, STDOUT and STDERR","messagePattern":"valid streams are STDIN, STDOUT and STDERR","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/container/opts.go","lineNumber":1139,"sourceCode":"\t\tif isValid := validator(split[2]); !isValid {\n\t\t\treturn val, fmt.Errorf(\"bad mode specified: %s\", mode)\n\t\t}\n\t\tval = fmt.Sprintf(\"%s:%s:%s\", split[0], containerPath, mode)\n\t}\n\n\tif !path.IsAbs(containerPath) {\n\t\treturn val, fmt.Errorf(\"%s is not an absolute path\", containerPath)\n\t}\n\treturn val, nil\n}\n\n// validateAttach validates that the specified string is a valid attach option.\nfunc validateAttach(val string) (string, error) {\n\ts := strings.ToLower(val)\n\tif slices.Contains([]string{\"stdin\", \"stdout\", \"stderr\"}, s) {\n\t\treturn s, nil\n\t}\n\treturn val, errors.New(\"valid streams are STDIN, STDOUT and STDERR\")\n}\n\nfunc toNetipAddrSlice(ips []string) []netip.Addr {\n\tif len(ips) == 0 {\n\t\treturn nil\n\t}\n\tnetIPs := make([]netip.Addr, 0, len(ips))\n\tfor _, ip := range ips {\n\t\taddr, err := netip.ParseAddr(ip)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tnetIPs = append(netIPs, addr)\n\t}\n\treturn netIPs\n}\n","sourceCodeStart":1121,"sourceCodeEnd":1156,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/container/opts.go#L1121-L1156","documentation":"Thrown by validateAttach when an --attach stream value is not one of stdin, stdout, stderr (case-insensitive). Docker can only attach to those three standard streams, so any other token is rejected. The check uses slices.Contains against the lowercased value.","triggerScenarios":"`docker run --attach STDIN --attach SERIAL ...` where SERIAL is invalid. Any --attach value outside {stdin,stdout,stderr} after ToLower.","commonSituations":"Typing a stream name wrong (STDOT, STDIN2). Passing a device/file name to --attach by mistake (thinking it attaches a file). Confusing --attach with --device or --mount.","solutions":["Use only STDIN, STDOUT, or STDERR (any case) with --attach.","If you meant to expose a device, use --device instead.","If you meant to mount a file/dir, use -v/--mount."],"exampleFix":"// before\ndocker run --attach STDOT alpine\n\n// after\ndocker run --attach STDOUT alpine","handlingStrategy":"validation","validationCode":"var validStreams = []string{\"stdin\", \"stdout\", \"stderr\"}\n\nfunc validAttach(val string) error {\n    if !slices.Contains(validStreams, strings.ToLower(val)) {\n        return errors.New(\"valid streams are STDIN, STDOUT and STDERR\")\n    }\n    return nil\n}\n\nfor _, a := range attachStreams {\n    if err := validAttach(a); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict the --attach token source to a constant set {STDIN,STDOUT,STDERR}.","Do not feed free-form user input directly to --attach.","Use --device for devices and --mount for files to avoid confusing them with streams."],"tags":["validation","cli-options","streams","container"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}