wavetermdev/waveterm · error
too many return values: %d
Error message
too many return values: %d
What it means
decodeRtnVals (pkg/wshutil/wshadapter.go:31) converts reflect.Call results of a wsh command method into (result, error) pairs for the RPC layer, accepting only 0, 1, or 2 return values. If a registered command method returns 3+ values, the adapter cannot map them to the RPC protocol and returns "too many return values: %d". This is a programming/declaration error in the command implementation, not a runtime condition.
Source
Thrown at pkg/wshutil/wshadapter.go:48
func decodeRtnVals(rtnVals []reflect.Value) (any, error) {
switch len(rtnVals) {
case 0:
return nil, nil
case 1:
errIf := rtnVals[0].Interface()
if errIf == nil {
return nil, nil
}
return nil, errIf.(error)
case 2:
errIf := rtnVals[1].Interface()
if errIf == nil {
return rtnVals[0].Interface(), nil
}
return rtnVals[0].Interface(), errIf.(error)
default:
return nil, fmt.Errorf("too many return values: %d", len(rtnVals))
}
}
func noImplHandler(handler *RpcResponseHandler) bool {
handler.SendResponseError(fmt.Errorf("command %q not implemented", handler.GetCommand()))
return true
}
func recodeCommandData(command string, data any, commandDataType reflect.Type) (any, error) {
if command == "" || commandDataType == nil {
return data, nil
}
methodDecl := WshCommandDeclMap[command]
if methodDecl == nil {
return data, fmt.Errorf("command %q not found", command)
}
commandDataPtr := reflect.New(commandDataType).Interface()
if data != nil {View on GitHub (pinned to a4447c1563)
Solutions
- Change the command method to return at most two values: (resultType, error) or just (error).
- Bundle extra return data into a struct and return that struct as the single result.
- Review wshrpc.WshCommandDeclMap declarations so the declared return type matches the method signature.
Example fix
// before
func (ws *WshServer) FooCommand(ctx context.Context, data FooData) (string, int, error) { ... }
// after
type FooResult struct { S string; N int }
func (ws *WshServer) FooCommand(ctx context.Context, data FooData) (*FooResult, error) { ... } Defensive patterns
Strategy: validation
Validate before calling
// compile-time-ish check that a command method has a legal return arity
m := reflect.TypeOf((*wshrpc.WshServer)(nil)).MethodByName("FooCommand")
t := m.Type
if t.NumOut() > 2 {
panic(fmt.Sprintf("FooCommand returns %d values; max is (result, error)", t.NumOut()))
} Try / catch
result, err := wshclient.RpcWshServerCommand(ctx, cmd, data)
if err != nil && strings.Contains(err.Error(), "too many return values") {
// command implementation has an illegal signature; fix the method, not the call site
} Prevention
- Follow the command convention strictly: methods must return (T, error), (error), or nothing.
- Add a unit test iterating WshCommandDeclMap checking reflect method return arity <= 2.
- Never copy ordinary multi-return helper signatures into *Command methods.
- Keep wshrpc decl types in sync with implementations after refactors.
When it happens
Trigger: Defining a WshServer command method (e.g. FooCommand) whose Go signature returns more than (result, error) or (error), then invoking it over wsh RPC; the reflect method lookup in findCmdMethod binds any method matching <cmd>command regardless of return arity.
Common situations: Refactoring a command to return extra context/a second value; copying a normal Go helper's multi-return signature into a command method; adding a generic type parameter set that changes the apparent return shape.
Related errors
- invalid number type %s
- invalid special wave argument type %s
- invalid map key type %s
- invalid pointer type %s
- invalid argument type %s
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/1d189a97b55b05c7.
Report an issue: GitHub.