wavetermdev/waveterm · error
cannot convert argument %s.%s type:%T idx:%d error:%v
Error message
cannot convert argument %s.%s type:%T idx:%d error:%v
What it means
Each positional argument from webCall.Args is converted from its JSON (interface{}) form to the method's declared parameter type via convertArgument. This error wraps the failure of that conversion: the JSON value's type/shape does not match the parameter type (e.g. a string where a number, a non-object where a struct, or malformed JSON for a typed field).
Source
Thrown at pkg/service/service.go:346
for idx := 0; idx < method.Type().NumIn(); idx++ {
argType := method.Type().In(idx)
if idx == 0 && argType == contextRType {
valueArgs = append(valueArgs, reflect.ValueOf(ctx))
continue
}
if argType == uiContextRType {
if webCall.UIContext == nil {
return webErrorRtn(fmt.Errorf("missing UIContext for %s.%s", webCall.Service, webCall.Method))
}
valueArgs = append(valueArgs, reflect.ValueOf(*webCall.UIContext))
continue
}
if argIdx >= len(webCall.Args) {
return webErrorRtn(fmt.Errorf("not enough arguments passed %s.%s idx:%d (type %T)", webCall.Service, webCall.Method, idx, argType))
}
nativeArg, err := convertArgument(argType, webCall.Args[argIdx])
if err != nil {
return webErrorRtn(fmt.Errorf("cannot convert argument %s.%s type:%T idx:%d error:%v", webCall.Service, webCall.Method, argType, idx, err))
}
valueArgs = append(valueArgs, reflect.ValueOf(nativeArg))
argIdx++
}
retValArr := method.Call(valueArgs)
return convertReturnValues(retValArr)
}
// ValidateServiceArg validates the argument type for a service method
// does not allow interfaces (and the obvious invalid types)
// arguments + return values have special handling for wave objects
func baseValidateServiceArg(argType reflect.Type) error {
if argType == waveObjUpdateRType {
// has special MarshalJSON method, so it is safe
return nil
}
switch argType.Kind() {
case reflect.Ptr, reflect.Slice, reflect.Array:View on GitHub (pinned to a4447c1563)
Solutions
- Match each arg's JSON type to the method signature: string->string, number->int/float64, boolean->bool, object->struct, and fix the caller's payload
- Look at the wrapped %v error and the idx/type in the message to pinpoint the offending argument and its expected Go type
- Regenerate the TypeScript client so argument types are enforced at compile time in the frontend
- For struct parameters, ensure the JSON object's fields marshal to the Go struct (field names via the Go JSON tags)
Example fix
// before Args: ["123", "true"] // strings where int and bool expected // after Args: [123, true]
Defensive patterns
Strategy: validation
Validate before calling
function assertArgTypes(call, expected) {
call.Args.forEach((arg, i) => {
const t = expected[i];
if (t === "number" && typeof arg !== "number") throw new Error(`arg ${i}: expected number, got ${typeof arg}`);
if (t === "string" && typeof arg !== "string") throw new Error(`arg ${i}: expected string, got ${typeof arg}`);
if (t === "boolean" && typeof arg !== "boolean") throw new Error(`arg ${i}: expected boolean, got ${typeof arg}`);
});
} Type guard
function isArgOf<T>(arg: unknown, chk: (a: unknown) => a is T): arg is T { return chk(arg); }
const isNum = (a: unknown): a is number => typeof a === "number" && !isNaN(a); Try / catch
const rtn = CallService(ctx, call);
if (rtn.Error.startsWith("cannot convert argument")) {
const idx = parseInt(rtn.Error.match(/idx:(\d+)/)?.[1] ?? "-1", 10);
console.error(`bad argument at position ${idx - offset}:`, call.Args[idx]);
} Prevention
- Never stringify numbers/booleans before sending as RPC args
- Parse user input into typed values (Number(), Boolean()) before dispatching
- Keep the generated TS client in sync so types are enforced statically
- For struct args, validate objects against their JSON schema/TS interface before sending
When it happens
Trigger: Passing an argument of the wrong JSON type — e.g. sending a string "123" where an int is required, a number where a bool is required, or an object missing required fields for a struct parameter; also nested type mismatches inside struct args.
Common situations: Hand-written RPC calls with untyped JSON (JavaScript numbers-as-strings); frontend sending null for non-pointer parameters; schema drift where the frontend still sends the old field format for a struct argument; locale/encoding issues corrupting string args.
Related errors
- invalid number type %s
- cannot convert %T to %s
- cannot convert %T to %s (idx %d is not a map, is %T)
- cannot convert %T to %s (key %s is not a map, is %T)
- error re-marshalling command data: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/99fa10f50a560f76.
Report an issue: GitHub.