{"record":{"id":"34c58e952513483d","repo":"wavetermdev/waveterm","slug":"command-cannot-be-empty","errorCode":null,"errorMessage":"command cannot be empty","messagePattern":"command cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrpc.go","lineNumber":778,"sourceCode":"\treturn handler.done.Load()\n}\n\nfunc (w *WshRpc) SendComplexRequest(command string, data any, opts *wshrpc.RpcOpts) (rtnHandler *RpcRequestHandler, rtnErr error) {\n\tif w.IsServerDone() {\n\t\treturn nil, errors.New(\"server is no longer running, cannot send new requests\")\n\t}\n\tif opts == nil {\n\t\topts = &wshrpc.RpcOpts{}\n\t}\n\ttimeoutMs := opts.Timeout\n\tif timeoutMs <= 0 {\n\t\ttimeoutMs = DefaultTimeoutMs\n\t}\n\tdefer func() {\n\t\tpanichandler.PanicHandler(\"SendComplexRequest\", recover())\n\t}()\n\tif command == \"\" {\n\t\treturn nil, fmt.Errorf(\"command cannot be empty\")\n\t}\n\thandler := &RpcRequestHandler{\n\t\tw:           w,\n\t\tctxCancelFn: &atomic.Pointer[context.CancelFunc]{},\n\t}\n\tvar cancelFn context.CancelFunc\n\thandler.ctx, cancelFn = context.WithTimeout(context.Background(), time.Duration(timeoutMs)*time.Millisecond)\n\thandler.ctxCancelFn.Store(&cancelFn)\n\tif !opts.NoResponse {\n\t\thandler.reqId = uuid.New().String()\n\t}\n\treq := &RpcMessage{\n\t\tCommand: command,\n\t\tReqId:   handler.reqId,\n\t\tData:    data,\n\t\tTimeout: timeoutMs,\n\t\tRoute:   opts.Route,\n\t}","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrpc.go#L760-L796","documentation":"SendComplexRequest requires a non-empty command string because the command identifies which RPC route/method to invoke on the remote side. An empty command would create a request packet that cannot be dispatched, so it fails fast before registration.","triggerScenarios":"Passing \"\" (or a variable that resolved to empty) as the command argument to SendComplexRequest/SendSimpleRequest; deriving the command name from config/env that is unset; typo leaving a constant blank.","commonSituations":"Command names built from user config or constants that were renamed/removed across versions; dynamic dispatch tables with missing entries; copy-paste leaving the command literal empty.","solutions":["Pass the correct command constant (e.g. wshrpc.Command_* names) as the command argument.","Validate the command string at the call site before invoking the request.","Check where the command name originates (config/env/registry) — the source is returning empty.","Autocomplete from the wshrpc command constants rather than typing string literals."],"exampleFix":"// before\nhandler, err := w.SendComplexRequest(cmd, args, &wshutil.RpcOpts{Route: route})\n// after\nif cmd == \"\" { return nil, fmt.Errorf(\"no command configured\") }\nhandler, err := w.SendComplexRequest(cmd, args, &wshutil.RpcOpts{Route: route})","handlingStrategy":"validation","validationCode":"func validateCommand(cmd string) error {\n    if strings.TrimSpace(cmd) == \"\" {\n        return fmt.Errorf(\"rpc command must be a non-empty string\")\n    }\n    return nil\n}","typeGuard":"func hasCommand(cmd string) bool {\n    return strings.TrimSpace(cmd) != \"\"\n}","tryCatchPattern":"handler, err := w.SendComplexRequest(cmd, args, opts)\nif err != nil && strings.Contains(err.Error(), \"command cannot be empty\") {\n    return fmt.Errorf(\"misconfigured rpc command for %s: %w\", route, err)\n}","preventionTips":["Reference wshrpc.Command_* constants instead of raw string literals.","Validate command names at config-load time, not at request time.","Guard dynamic dispatch tables against missing/empty entries.","Add a startup assertion that all configured commands are non-empty."],"tags":["rpc","invalid-argument","missing-command"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}