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

  1. Change the command method to return at most two values: (resultType, error) or just (error).
  2. Bundle extra return data into a struct and return that struct as the single result.
  3. 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

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


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/1d189a97b55b05c7. Report an issue: GitHub.