wavetermdev/waveterm · error

invalid routeid %q

Error message

invalid routeid %q

What it means

RegisterTrustedLeaf registers an RPC client as a trusted leaf link and binds a route to it. Before doing anything it validates the routeId with isBindableRouteId, which rejects empty routeIds and any routeId starting with the control prefix or the link-route prefix (those namespaces are reserved for internal router traffic). If the routeId falls in a reserved/empty namespace, the registration is refused with this error.

Source

Thrown at pkg/wshutil/wshrouter.go:638

	if lm == nil {
		return nil
	}
	lmCopy := *lm
	return &lmCopy
}

func (router *WshRouter) GetLinkIdForRoute(routeId string) baseds.LinkId {
	lm := router.getLinkForRoute(routeId)
	if lm == nil {
		return baseds.NoLinkId
	}
	return lm.linkId
}

// only for leaves
func (router *WshRouter) RegisterTrustedLeaf(rpc AbstractRpcClient, routeId string) (baseds.LinkId, error) {
	if !isBindableRouteId(routeId) {
		return 0, fmt.Errorf("invalid routeid %q", routeId)
	}
	linkId := router.RegisterUntrustedLink(rpc)
	router.trustLink(linkId, LinkKind_Leaf)
	router.bindRoute(linkId, routeId, true)
	return linkId, nil
}

// only for routers
func (router *WshRouter) RegisterTrustedRouter(rpc AbstractRpcClient) baseds.LinkId {
	linkId := router.RegisterUntrustedLink(rpc)
	router.trustLink(linkId, LinkKind_Router)
	return linkId
}

func (router *WshRouter) RegisterUpstream(rpc AbstractRpcClient) baseds.LinkId {
	if router.IsRootRouter() {
		panic("cannot register upstream for root router")
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check the routeId value at the call site; ensure it is a non-empty, user-level route name that does not start with the control prefix or the link-route prefix
  2. Guard the call with isBindableRouteId semantics: skip or fix calls where routeId is empty or prefixed with the reserved prefixes
  3. Trace where the routeId is generated (config, blockid, connection id) and fix the generation so it produces a valid named route

Example fix

// before
linkId, err := router.RegisterTrustedLeaf(rpc, routeId) // routeId may be "" or "*ctrl:..."
// after
if routeId == "" || strings.HasPrefix(routeId, ControlPrefix) || strings.HasPrefix(routeId, RoutePrefix_Link) {
    return fmt.Errorf("refusing to register leaf with reserved routeid %q", routeId)
}
linkId, err := router.RegisterTrustedLeaf(rpc, routeId)
Defensive patterns

Strategy: validation

Validate before calling

func validLeafRouteId(id string) bool {
    return id != "" && !strings.HasPrefix(id, ControlPrefix) && !strings.HasPrefix(id, RoutePrefix_Link)
}
if !validLeafRouteId(routeId) {
    return fmt.Errorf("cannot register leaf: invalid routeid %q", routeId)
}
linkId, err := router.RegisterTrustedLeaf(rpc, routeId)

Type guard

func isSet(s string) bool { return strings.TrimSpace(s) != "" }
if !isSet(routeId) { return }

Prevention

When it happens

Trigger: Calling WshRouter.RegisterTrustedLeaf(rpc, routeId) with routeId == "", a routeId beginning with ControlPrefix (control-channel namespace), or a routeId beginning with RoutePrefix_Link (per-link route namespace).

Common situations: Constructing a routeId programmatically from a variable that is empty or unset; accidentally passing an internal control/link route id (e.g. one obtained from the router's own reserved prefixes) to RegisterTrustedLeaf instead of a normal named route; copy-pasting a control-channel route string into leaf registration code.

Related errors


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