{"record":{"id":"42d0d38b73c76ba5","repo":"wavetermdev/waveterm","slug":"oscnum-must-be-5-characters","errorCode":null,"errorMessage":"oscNum must be 5 characters","messagePattern":"oscNum must be 5 characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshutil.go","lineNumber":76,"sourceCode":"\tdst[0] = ESC\n\tdst[1] = ']'\n\tcopy(dst[2:], oscNum)\n\tdst[len(oscNum)+2] = ';'\n}\n\nfunc oscPrefixLen(oscNum string) int {\n\treturn 3 + len(oscNum)\n}\n\nfunc makeOscPrefix(oscNum string) []byte {\n\toutput := make([]byte, oscPrefixLen(oscNum))\n\tcopyOscPrefix(output, oscNum)\n\treturn output\n}\n\nfunc EncodeWaveOSCBytes(oscNum string, barr []byte) ([]byte, error) {\n\tif len(oscNum) != 5 {\n\t\treturn nil, fmt.Errorf(\"oscNum must be 5 characters\")\n\t}\n\tconst maxSize = 64 * 1024 * 1024 // 64 MB\n\tif len(barr) > maxSize {\n\t\treturn nil, fmt.Errorf(\"input data too large\")\n\t}\n\thasControlChars := false\n\tfor _, b := range barr {\n\t\tif b < 0x20 || b == 0x7F {\n\t\t\thasControlChars = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !hasControlChars {\n\t\t// If no control characters, directly construct the output\n\t\t// \\x1b] (2) + WaveOSC + ; (1) + message + \\x07 (1)\n\t\toutput := make([]byte, oscPrefixLen(oscNum)+len(barr)+1)\n\t\tcopyOscPrefix(output, oscNum)\n\t\tcopy(output[oscPrefixLen(oscNum):], barr)","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshutil.go#L58-L94","documentation":"EncodeWaveOSCBytes requires the OSC escape number (oscNum) to be exactly 5 characters, matching the internal Wave OSC prefix format. Passing any other length string is rejected up front because it would produce a malformed escape sequence the terminal parser cannot recognize.","triggerScenarios":"Calling EncodeWaveOSCBytes, AdaptMsgChToPty, or EncodeWaveOSCMessageEx with an oscNum/oscEsc argument whose len != 5, e.g. \"2000\" or \"1337\" (4 chars) instead of \"1337;\".","commonSituations":"Typos in the OSC escape constant; removing the trailing semicolon; hardcoding a 4-digit OSC number from other terminal conventions (e.g. iTerm2's 1337).","solutions":["Pass a 5-character OSC number including the trailing semicolon, e.g. \"1337;\".","Verify the constant used matches the one Wave's decoder (DecodeWaveOSCBytes) expects.","Add a startup-time assertion if the oscNum is constructed dynamically."],"exampleFix":"// before\nEncodeWaveOSCBytes(\"1337\", barr)\n// after\nEncodeWaveOSCBytes(\"1337;\", barr) // must be exactly 5 chars","handlingStrategy":"validation","validationCode":"if len(oscNum) != 5 {\n    return errors.New(\"oscNum must be exactly 5 characters, e.g. \\\"1337;\\\"\")\n}","typeGuard":"func isValidOscNum(s string) bool { return len(s) == 5 }","tryCatchPattern":"if !isValidOscNum(oscNum) {\n    return fmt.Errorf(\"bad oscNum %q\", oscNum)\n}\nbarr, err := EncodeWaveOSCBytes(oscNum, barr)\nif err != nil { return err }","preventionTips":["Use a named constant for the OSC number instead of string literals","Always include the trailing semicolon in the Wave OSC number","Write a unit test asserting the constant length"],"tags":["go","validation","osc"],"backgroundTag":"invalid-argument-format","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}