slackhq/nebula · error
-%s and -%s both set to %q, only one output may write to std
Error message
-%s and -%s both set to %q, only one output may write to stdout
What it means
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.
Source
Thrown at cmd/nebula-cert/stdio.go:40
// ioClaims tracks which flags have claimed stdin and stdout during a single
// command invocation so we can refuse a second flag asking for the same
// stream.
type ioClaims struct {
in string
out string
}
func (c *ioClaims) claimIn(flagName string) error {
if c.in != "" && c.in != flagName {
return fmt.Errorf("-%s and -%s both set to %q, only one input may read from stdin", c.in, flagName, stdioPath)
}
c.in = flagName
return nil
}
func (c *ioClaims) claimOut(flagName string) error {
if c.out != "" && c.out != flagName {
return fmt.Errorf("-%s and -%s both set to %q, only one output may write to stdout", c.out, flagName, stdioPath)
}
c.out = flagName
return nil
}
// reserveInputs walks alternating (flagName, path) pairs and claims stdin
// for any path equal to stdioPath. It must be called before any input is
// read so a conflict can be reported immediately instead of blocking on
// io.ReadAll while waiting for input that will never arrive.
func reserveInputs(claims *ioClaims, pairs ...string) error {
return reserveStdio(claims, "reserveInputs", (*ioClaims).claimIn, pairs)
}
// reserveOutputs walks alternating (flagName, path) pairs and claims stdout
// for any path equal to stdioPath. It must be called before any output is
// written so a conflict cannot leave one stream half written before the
// second flag fails.
func reserveOutputs(claims *ioClaims, pairs ...string) error {View on GitHub (pinned to dd8f660c0a)
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
Example fix
// before nebula-cert sign -ca ca.pem -key ca.key -name host -out-crt - -out-qr - // after nebula-cert sign -ca ca.pem -key ca.key -name host -out-crt -
Defensive patterns
Strategy: validation
Validate before calling
func validateOutputs(paths map[string]string) error {
n := 0
for _, p := range paths {
if p == "-" { n++ }
}
if n > 1 {
return fmt.Errorf("%d output flags write stdout; only one allowed", n)
}
return nil
} Try / catch
out, err := exec.Command("nebula-cert", args...).CombinedOutput()
if err != nil && strings.Contains(string(out), "only one output may write to stdout") {
log.Printf("fix stdout flags: %s", out)
} Prevention
- Only one output flag may be '-'
- Set file paths for all additional outputs
- Validate wrapper-script variables before building the command line
When it happens
Trigger: 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.
Common situations: User passes '-' for multiple output flags expecting both to print; scripts with unset path variables defaulting to '-'.
Related errors
- -%s and -%s both set to %q, only one input may read from std
- error while marshalling certificate: %s
- error while writing out-crt: %s
- error while generating qr code: %s
- error while writing out-qr: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/86a199f8803d1273.
Report an issue: GitHub.