{"record":{"id":"ab5e75635cc2035f","repo":"docker/cli","slug":"error-reading-from-stdin-data-is-empty-ab5e75","errorCode":null,"errorMessage":"error reading from STDIN: data is empty","messagePattern":"error reading from STDIN: data is empty","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/secret/create.go","lineNumber":134,"sourceCode":"// as defined by [MaxSecretSize] in SwarmKit.\n//\n// [MaxSecretSize]: https://pkg.go.dev/github.com/moby/swarmkit/v2@v2.0.0-20250103191802-8c1959736554/api/validation#MaxSecretSize\nconst maxSecretSize = 500 * 1024 // 500KB\n\n// readSecretData reads the secret from either stdin or the given fileName.\n//\n// It reads up to twice the maximum size of the secret ([maxSecretSize]),\n// just in case swarm's limit changes; this is only a safeguard to prevent\n// reading arbitrary files into memory.\nfunc readSecretData(in io.Reader, fileName string) ([]byte, error) {\n\tswitch fileName {\n\tcase \"-\":\n\t\tdata, err := io.ReadAll(io.LimitReader(in, 2*maxSecretSize))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading from STDIN: %w\", err)\n\t\t}\n\t\tif len(data) == 0 {\n\t\t\treturn nil, errors.New(\"error reading from STDIN: data is empty\")\n\t\t}\n\t\treturn data, nil\n\tcase \"\":\n\t\treturn nil, errors.New(\"secret file is required\")\n\tdefault:\n\t\t// Open file with [FILE_FLAG_SEQUENTIAL_SCAN] on Windows, which\n\t\t// prevents Windows from aggressively caching it. We expect this\n\t\t// file to be only read once. Given that this is expected to be\n\t\t// a small file, this may not be a significant optimization, so\n\t\t// we could choose to omit this, and use a regular [os.Open].\n\t\t//\n\t\t// [FILE_FLAG_SEQUENTIAL_SCAN]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN\n\t\tf, err := sequential.Open(fileName)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading from %s: %w\", fileName, err)\n\t\t}\n\t\tdefer f.Close()\n\t\tdata, err := io.ReadAll(io.LimitReader(f, 2*maxSecretSize))","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/secret/create.go#L116-L152","documentation":"Thrown by readSecretData when the data source is stdin ('-') and the read returns zero bytes. An empty secret is not permitted, so the create is refused (secret/create.go lines 133-135).","triggerScenarios":"Running 'echo -n \"\" | docker secret create mysec -' or piping an empty stream/file as the secret content via '-'.","commonSituations":"Empty env var piped in; upstream command produced no output; redirecting from /dev/null.","solutions":["Ensure the piped stdin contains non-empty secret data.","Use a file with actual content: 'docker secret create mysec ./secret.txt'.","Verify the upstream producer of the data emits content before piping."],"exampleFix":"# before\nprintf '' | docker secret create mysec -\n# after\nprintf '%s' \"$SECRET_VALUE\" | docker secret create mysec -","handlingStrategy":"validation","validationCode":"// Validate non-empty stdin before creating the secret\ndata, err := io.ReadAll(io.LimitReader(in, 2*maxSecretSize))\nif err != nil { return err }\nif len(data) == 0 {\n    return fmt.Errorf(\"stdin secret data is empty\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check the upstream producer emits non-empty output before piping.","Prefer a verified non-empty file over stdin for secrets.","Log data length (not contents) to catch empty inputs in CI."],"tags":["secret","stdin","swarm","docker","go","cli"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}