{"record":{"id":"86a199f8803d1273","repo":"slackhq/nebula","slug":"s-and-s-both-set-to-q-only-one-output-may-wr","errorCode":null,"errorMessage":"-%s and -%s both set to %q, only one output may write to stdout","messagePattern":"-(.+?) and -(.+?) both set to %q, only one output may write to stdout","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/nebula-cert/stdio.go","lineNumber":40,"sourceCode":"// ioClaims tracks which flags have claimed stdin and stdout during a single\n// command invocation so we can refuse a second flag asking for the same\n// stream.\ntype ioClaims struct {\n\tin  string\n\tout string\n}\n\nfunc (c *ioClaims) claimIn(flagName string) error {\n\tif c.in != \"\" && c.in != flagName {\n\t\treturn fmt.Errorf(\"-%s and -%s both set to %q, only one input may read from stdin\", c.in, flagName, stdioPath)\n\t}\n\tc.in = flagName\n\treturn nil\n}\n\nfunc (c *ioClaims) claimOut(flagName string) error {\n\tif c.out != \"\" && c.out != flagName {\n\t\treturn fmt.Errorf(\"-%s and -%s both set to %q, only one output may write to stdout\", c.out, flagName, stdioPath)\n\t}\n\tc.out = flagName\n\treturn nil\n}\n\n// reserveInputs walks alternating (flagName, path) pairs and claims stdin\n// for any path equal to stdioPath. It must be called before any input is\n// read so a conflict can be reported immediately instead of blocking on\n// io.ReadAll while waiting for input that will never arrive.\nfunc reserveInputs(claims *ioClaims, pairs ...string) error {\n\treturn reserveStdio(claims, \"reserveInputs\", (*ioClaims).claimIn, pairs)\n}\n\n// reserveOutputs walks alternating (flagName, path) pairs and claims stdout\n// for any path equal to stdioPath. It must be called before any output is\n// written so a conflict cannot leave one stream half written before the\n// second flag fails.\nfunc reserveOutputs(claims *ioClaims, pairs ...string) error {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cmd/nebula-cert/stdio.go#L22-L58","documentation":"Symmetric to claimIn: only one output flag may write to stdout. ioClaims.out records the flag that claimed stdout; claimOut errors when a second, different output flag also requests '-', because two outputs cannot share the same stream without interleaving corruption.","triggerScenarios":"claimOut is called with a flag name different from the one already holding c.out — e.g. both -out-crt and -out-qr set to '-' during signCert.","commonSituations":"User passes '-' for multiple output flags expecting both to print; scripts with unset path variables defaulting to '-'.","solutions":["Set only ONE output flag to '-' and give other outputs real file paths","Omit optional outputs like -out-qr when writing the cert to stdout","Fix variables in wrapper scripts so paths are not blank"],"exampleFix":"// before\nnebula-cert sign -ca ca.pem -key ca.key -name host -out-crt - -out-qr -\n// after\nnebula-cert sign -ca ca.pem -key ca.key -name host -out-crt -","handlingStrategy":"validation","validationCode":"func validateOutputs(paths map[string]string) error {\n    n := 0\n    for _, p := range paths {\n        if p == \"-\" { n++ }\n    }\n    if n > 1 {\n        return fmt.Errorf(\"%d output flags write stdout; only one allowed\", n)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"out, err := exec.Command(\"nebula-cert\", args...).CombinedOutput()\nif err != nil && strings.Contains(string(out), \"only one output may write to stdout\") {\n    log.Printf(\"fix stdout flags: %s\", out)\n}","preventionTips":["Only one output flag may be '-'","Set file paths for all additional outputs","Validate wrapper-script variables before building the command line"],"tags":["go","cli","stdout","flag-conflict"],"backgroundTag":"ambiguous-stdout-output","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}