{"record":{"id":"62454734af39f14c","repo":"wavetermdev/waveterm","slug":"authenticatejobmanagerverify-can-only-be-called-on","errorCode":null,"errorMessage":"authenticatejobmanagerverify can only be called on root router","messagePattern":"authenticatejobmanagerverify can only be called on root router","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":219,"sourceCode":"\t\t}\n\t}\n\n\tif rtnData.RpcContext == nil {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no rpccontext in token response\")\n\t}\n\tif rtnData.RouteId == \"\" {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no routeid in token response\")\n\t}\n\tlog.Printf(\"wshrouter authenticate-token success linkid=%d routeid=%q\", linkId, rtnData.RouteId)\n\timpl.Router.trustLink(linkId, LinkKind_Leaf)\n\timpl.Router.bindRoute(linkId, rtnData.RouteId, true)\n\n\treturn rtnData, nil\n}\n\nfunc (impl *WshRouterControlImpl) AuthenticateJobManagerVerifyCommand(ctx context.Context, data wshrpc.CommandAuthenticateJobManagerData) error {\n\tif !impl.Router.IsRootRouter() {\n\t\treturn fmt.Errorf(\"authenticatejobmanagerverify can only be called on root router\")\n\t}\n\n\tif data.JobId == \"\" {\n\t\treturn fmt.Errorf(\"no jobid in authenticatejobmanager message\")\n\t}\n\tif data.JobAuthToken == \"\" {\n\t\treturn fmt.Errorf(\"no jobauthtoken in authenticatejobmanager message\")\n\t}\n\n\tjob, err := wstore.DBMustGet[*waveobj.Job](ctx, data.JobId)\n\tif err != nil {\n\t\tlog.Printf(\"wshrouter authenticate-jobmanager-verify error jobid=%q: failed to get job: %v\", data.JobId, err)\n\t\treturn fmt.Errorf(\"failed to get job: %w\", err)\n\t}\n\n\tif job.JobAuthToken != data.JobAuthToken {\n\t\tlog.Printf(\"wshrouter authenticate-jobmanager-verify error jobid=%q: invalid jobauthtoken\", data.JobId)\n\t\treturn fmt.Errorf(\"invalid jobauthtoken\")","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L201-L237","documentation":"AuthenticateJobManagerVerifyCommand is a root-only control RPC: only the root router holds the wstore job records needed to verify a job auth token. If the router receiving this call is not the root router, it immediately rejects the call with this error.","triggerScenarios":"Routing Command_AuthenticateJobManagerVerify to a non-root (relay/leaf) router — e.g. wrong RpcOpts.Route, or calling the command locally on a middle-layer router instance instead of the root.","commonSituations":"Job manager configured to talk to a downstream wavelock/ssh relay instead of the root wave process; test harness instantiating a child router and issuing the verify command against it.","solutions":["Ensure the RPC is routed to ControlRootRoute so it lands on the root router.","Connect to the actual root wave process for job-manager verification instead of a relay.","Check impl.Router.IsRootRouter() configuration of the instance you are calling; create/use the root router.","Fix tests/harnesses to use a root router for this command."],"exampleFix":"// before\nerr := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, data, &wshrpc.RpcOpts{Route: someRelayRoute})\n// after\nerr := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, data, &wshrpc.RpcOpts{Route: wshutil.ControlRootRoute})","handlingStrategy":"validation","validationCode":"// only send this command when connected to the root\nif !conn.TargetIsRootRouter() {\n    return fmt.Errorf(\"refusing: authenticatejobmanagerverify must go to the root router\")\n}","typeGuard":null,"tryCatchPattern":"err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, data, &wshrpc.RpcOpts{Route: wshutil.ControlRootRoute})\nif err != nil && strings.Contains(err.Error(), \"can only be called on root router\") {\n    return fmt.Errorf(\"misrouted RPC: fix the RpcOpts.Route to %s\", wshutil.ControlRootRoute)\n}","preventionTips":["Route job-manager verification RPCs to ControlRootRoute only.","Never call root-only control commands against relay/leaf routers.","In tests, instantiate a root router when exercising this command."],"tags":["rpc","routing","authentication"],"backgroundTag":"rpc-only-valid-on-root-router","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}