{"record":{"id":"8415a2fe292ecd88","repo":"larksuite/cli","slug":"stdin-is-empty-did-you-forget-to-pipe-input","errorCode":null,"errorMessage":"stdin is empty (did you forget to pipe input?)","messagePattern":"stdin is empty \\(did you forget to pipe input\\?\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmdutil/resolve.go","lineNumber":43,"sourceCode":"// Allows callers to bypass shell quoting issues (especially Windows PowerShell 5)\n// by reading JSON from a file (@path) or piping via stdin (-).\nfunc ResolveInput(raw string, stdin io.Reader, fileIO fileio.FileIO) (string, error) {\n\tif raw == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\t// stdin\n\tif raw == \"-\" {\n\t\tif stdin == nil {\n\t\t\treturn \"\", fmt.Errorf(\"stdin is not available\")\n\t\t}\n\t\tdata, err := io.ReadAll(stdin)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to read stdin: %w\", err)\n\t\t}\n\t\ts := strings.TrimSpace(string(data))\n\t\tif s == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"stdin is empty (did you forget to pipe input?)\")\n\t\t}\n\t\treturn s, nil\n\t}\n\n\t// escape: @@... → literal @... (no file read)\n\tif strings.HasPrefix(raw, \"@@\") {\n\t\treturn raw[1:], nil\n\t}\n\n\t// file: @path\n\tif strings.HasPrefix(raw, \"@\") {\n\t\tpath := strings.TrimSpace(raw[1:])\n\t\tif path == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"file path cannot be empty after @\")\n\t\t}\n\t\tdata, err := ReadInputFile(fileIO, path)\n\t\tif err != nil {\n\t\t\treturn \"\", err","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/cmdutil/resolve.go#L25-L61","documentation":"ResolveInput trims whitespace from stdin data and rejects it when nothing remains. The library throws this so commands never silently submit an empty body caused by an unplumbed or accidentally empty pipe. The message is a hint that the user likely forgot to pipe input.","triggerScenarios":"Passing \"-\" as the input to ParseOptionalBody/ParseJSONMap while running the command without piping anything (or piping only whitespace/newlines) into stdin.","commonSituations":"Forgetting the echo/cat pipe in a shell one-liner; piping an empty file; copying a documented pipeline but omitting the producer; CI step where the upstream step produced no output.","solutions":["Pipe the payload into the command, e.g. echo '{...}' | lark-cli cmd --body -","Verify the upstream producer actually emits non-empty output","Use @path-to-file instead of \"-\" if the payload already exists on disk","Quote/escape correctly so \"-\" is passed as the flag value, not consumed by the shell"],"exampleFix":"// before\nlark-cli im message create --body -\n// after\necho '{\"receive_id\":\"ou_x\",\"content\":\"{}\"}' | lark-cli im message create --body -","handlingStrategy":"validation","validationCode":"// before running with \"-\":\nif [ -t 0 ]; then echo \"stdin is a TTY: nothing piped\"; exit 1; fi\n# or in Go:\nfi, _ := os.Stdin.Stat(); if fi.Mode()&os.ModeCharDevice != 0 { /* no piped input */ }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"stdin is empty\") {\n    fmt.Fprintln(os.Stderr, \"hint: pipe the JSON body, e.g. echo '{...}' | cmd --body -\")\n}","preventionTips":["Always pair \"-\" with a producer in shell one-liners","Check upstream command exit status and output size before piping","Use @file when the payload is static","Verify CI steps actually emit output"],"tags":["stdin","cli","empty-input"],"backgroundTag":"empty-stdin-input","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}