wavetermdev/waveterm · error

command %q invalid multi arg payload

Error message

command %q invalid multi arg payload

What it means

For commands declared with multiple argument types, the adapter expects the payload to be a wshrpc.MultiArg struct (a struct wrapping an Args slice) and type-asserts the decoded payload to it. If the payload does not implement/convert to MultiArg, this error is returned. It protects the variadic-style RPC commands from receiving a single raw value.

Source

Thrown at pkg/wshutil/wshadapter.go:119

		var callParams []reflect.Value
		callParams = append(callParams, reflect.ValueOf(handler.Context()))
		commandDataTypes := methodDecl.GetCommandDataTypes()
		if len(commandDataTypes) == 1 {
			cmdData, err := recodeCommandData(cmd, handler.GetCommandRawData(), commandDataTypes[0])
			if err != nil {
				handler.SendResponseError(err)
				return true
			}
			callParams = append(callParams, reflect.ValueOf(cmdData))
		} else if len(commandDataTypes) > 1 {
			multiArgAny, err := recodeCommandData(cmd, handler.GetCommandRawData(), multiArgRType)
			if err != nil {
				handler.SendResponseError(err)
				return true
			}
			multiArg, ok := multiArgAny.(wshrpc.MultiArg)
			if !ok {
				handler.SendResponseError(fmt.Errorf("command %q invalid multi arg payload", cmd))
				return true
			}
			if len(multiArg.Args) != len(commandDataTypes) {
				handler.SendResponseError(fmt.Errorf("command %q expected %d args, got %d", cmd, len(commandDataTypes), len(multiArg.Args)))
				return true
			}
			for idx, commandDataType := range commandDataTypes {
				cmdData, err := recodeCommandData(cmd, multiArg.Args[idx], commandDataType)
				if err != nil {
					handler.SendResponseError(err)
					return true
				}
				callParams = append(callParams, reflect.ValueOf(cmdData))
			}
		}
		if methodDecl.CommandType == wshrpc.RpcType_Call {
			rtnVals := implMethod.Call(callParams)
			rtnData, rtnErr := decodeRtnVals(rtnVals)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Wrap the arguments in wshrpc.MultiArg{Args: []any{arg1, arg2, ...}} with one entry per declared argument type.
  2. Check methodDecl.GetCommandDataTypes() for the command to confirm it is genuinely multi-arg before choosing a payload shape.
  3. If the command now takes a single argument in your version, upgrade/downgrade so both sides agree on the declaration.

Example fix

// before: single raw value for a multi-arg command
payload := domainScope
// after: wrap in MultiArg
payload := wshrpc.MultiArg{Args: []any{domainScope, varName, value}}
Defensive patterns

Strategy: type-guard

Validate before calling

// Only send MultiArg payloads to commands declared multi-arg
decl := wshutil.WshCommandDeclMap[cmd]
if decl != nil && len(decl.GetCommandDataTypes()) > 1 {
    payload = wshrpc.MultiArg{Args: args}
}

Type guard

func asMultiArg(v any) (*wshrpc.MultiArg, bool) {
    ma, ok := v.(wshrpc.MultiArg)
    if !ok { return nil, false }
    return &ma, true
}

Try / catch

err := client.SendRpcRequest(ctx, cmd, payload)
if err != nil && strings.Contains(err.Error(), "invalid multi arg payload") {
    return fmt.Errorf("%s requires wshrpc.MultiArg{Args: [...]}, got %T", cmd, payload)
}

Prevention

When it happens

Trigger: Calling a multi-argument command (methodDecl has >1 command data types) with a plain payload instead of wshrpc.MultiArg{Args: [...]}; sending a single arg directly rather than wrapped in the Args slice.

Common situations: Hand-building RPC payloads in scripts or tests for commands like SetDomainVar/AppendDomainVar that take multiple typed args; forgetting the MultiArg wrapper after changing a command from single-arg to multi-arg.

Related errors


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