{"record":{"id":"da0b78530944ae61","repo":"joewalnes/websocketd","slug":"please-only-specify-one-of-binary-and-passstde","errorCode":null,"errorMessage":"please only specify one of --binary and --passstderr","messagePattern":"please only specify one of --binary and --passstderr","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config.go","lineNumber":153,"sourceCode":"\tif ssl {\n\t\tif certFile == \"\" || keyFile == \"\" {\n\t\t\treturn fmt.Errorf(\"please specify both --sslcert and --sslkey when requesting --ssl\")\n\t\t}\n\t} else {\n\t\tif certFile != \"\" || keyFile != \"\" {\n\t\t\treturn fmt.Errorf(\"you should not be using --ssl* flags when there is no --ssl option\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// validateBinaryPassStderr checks that --binary and --passstderr aren't both\n// set. Tagging binary chunks as JSON isn't implemented (--passstderr always\n// reads line by line), so combining the two would silently discard --binary\n// instead of behaving as either flag alone.\nfunc validateBinaryPassStderr(binary, passStderr bool) error {\n\tif binary && passStderr {\n\t\treturn fmt.Errorf(\"please only specify one of --binary and --passstderr\")\n\t}\n\treturn nil\n}\n\n// validateAnyOrigin checks that --anyorigin is not combined with an actual\n// origin policy. The flags say opposite things, and silently preferring one\n// would hide operator confusion.\nfunc validateAnyOrigin(anyOrigin, sameOrigin bool, allowOrigins []string) error {\n\tif anyOrigin && (sameOrigin || allowOrigins != nil) {\n\t\treturn fmt.Errorf(\"--anyorigin means 'accept any origin' and cannot be combined with --sameorigin or --origin, which restrict it\")\n\t}\n\treturn nil\n}\n\n// validateMaxFrameSize rejects negative --maxframesize values. The read\n// limit is only applied for positive values, so a negative value silently\n// meant \"unlimited\" — the one value an operator can pass that quietly\n// removes the DoS protection the flag exists for (issue #472).","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/joewalnes/websocketd/blob/7a8683dc7f9778dc615945aaed2a8dc77290227b/config.go#L135-L171","documentation":"validateBinaryPassStderr rejects using --binary together with --passstderr. Tagging binary chunks as JSON is not implemented (--passstderr reads line by line), so combining them would silently discard --binary; the server refuses the combination instead.","triggerScenarios":"Running websocketd with both --binary and --passstderr set at startup.","commonSituations":"Adding --passstderr to a setup that already used --binary to capture stderr output; misunderstanding that the flags are mutually exclusive transport/output modes.","solutions":["Choose one: keep --binary for binary-safe stdout frames, or --passstderr to forward stderr as JSON-tagged messages","If you need both binary data and stderr, run stderr forwarding in a wrapper script instead"],"exampleFix":"// before\nwebsocketd --binary --passstderr --port=8080 ./app\n// after\nwebsocketd --binary --port=8080 ./app","handlingStrategy":"validation","validationCode":"if (args.includes('--binary') && args.includes('--passstderr')) throw new Error('--binary and --passstderr are mutually exclusive');","typeGuard":"const outputMode = (c) => ['binary','passstderr','default'].find(m => m === (c.binary ? 'binary' : c.passstderr ? 'passstderr' : 'default'));","tryCatchPattern":"try { startServer(args) } catch (e) { if (/only specify one of --binary/.test(e)) console.error('pick a single output mode'); throw e; }","preventionTips":["Decide one output mode per deployment; do not merge flag sets from different examples","If you need binary frames plus stderr, forward stderr from a wrapper script instead"],"tags":["cli","config-validation","mutually-exclusive-flags"],"backgroundTag":"conflicting-cli-flags","analyzedSha":"7a8683dc7f9778dc615945aaed2a8dc77290227b","analyzedAt":"2026-09-03T13:52:22.309Z","contentChangedAt":"2026-09-03T13:52:22.309Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}