wavetermdev/waveterm · error

invalid pointer type %s

Error message

invalid pointer type %s

What it means

Thrown when a service method parameter is a pointer whose element kind is not Struct (e.g. *string, *int, *map). The RPC bridge only supports pointer-to-struct parameters (populated from JSON objects); other pointer types are unconvertible from JSON and are rejected before the JSON shape is even examined.

Source

Thrown at pkg/service/service.go:254

			return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
		}
		return convertComplex(argType, jsonArg)

	case reflect.Slice:
		if jsonType.Kind() != reflect.Slice {
			return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
		}
		return convertComplex(argType, jsonArg)

	case reflect.Struct:
		if jsonType.Kind() != reflect.Map {
			return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
		}
		return convertComplex(argType, jsonArg)

	case reflect.Ptr:
		if argType.Elem().Kind() != reflect.Struct {
			return nil, fmt.Errorf("invalid pointer type %s", argType)
		}
		if jsonType.Kind() != reflect.Map {
			return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
		}
		return convertComplex(argType, jsonArg)

	default:
		return nil, fmt.Errorf("invalid argument type %s", argType)
	}
}

func isNilable(val reflect.Value) bool {
	switch val.Kind() {
	case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface, reflect.Chan, reflect.Func:
		return true
	}
	return false

View on GitHub (pinned to a4447c1563)

Solutions

  1. Change the parameter to a plain value type (string, int) or a pointer-to-struct; handle optionality inside the method.
  2. Wrap the optional scalar in a struct (e.g. type Opt struct{ Value string }) and accept *Opt.
  3. If nil-vs-zero matters, accept an interface/special arg type supported by the bridge or split into two methods.

Example fix

// before
func (s *Svc) SetName(name *string) error

// after
type SetNameOpts struct { Name string }
func (s *Svc) SetName(opts SetNameOpts) error { ... }
Defensive patterns

Strategy: validation

Validate before calling

// check the Go signature before calling: only *Struct pointer params are supported
if (paramKind === 'ptr' && pointedKind !== 'struct') throw new Error('unsupported *T param; wrap in struct');

Try / catch

try {
  const rtn = await callService(svc, method, args);
  if (rtn.error?.includes('invalid pointer type')) throw new Error('method signature uses unsupported pointer type');
} catch (e) { /* redesign call: pass value type or *struct wrapper */ }

Prevention

When it happens

Trigger: A registered service method declares *string, *int, *[]string, or another non-struct pointer parameter, and a client calls it via CallService. The error fires regardless of what JSON value was passed.

Common situations: Service authors using pointer types for optional scalars (a common Go idiom) without realizing the RPC layer can't build them; refactoring signatures to add optional params as pointers.

Related errors


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