{"record":{"id":"b5503b774898fa28","repo":"wavetermdev/waveterm","slug":"error-authenticating-with-upstream-v","errorCode":null,"errorMessage":"error authenticating with upstream: %v","messagePattern":"error authenticating with upstream: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/wsh/cmd/wshcmd-connserver.go","lineNumber":343,"sourceCode":"\t\t\tpanichandler.PanicHandler(\"serverRunRouterDomainSocket:ReadLoop\", recover())\n\t\t}()\n\t\tdefer func() {\n\t\t\tlog.Printf(\"upstream domain socket closed, shutting down\")\n\t\t\twshutil.DoShutdown(\"\", 0, true)\n\t\t}()\n\t\twshutil.AdaptStreamToMsgCh(conn, upstreamProxy.FromRemoteCh, nil)\n\t}()\n\n\t// register the domain socket connection as upstream\n\trouter.RegisterUpstream(upstreamProxy)\n\n\t// use the router's control RPC to authenticate with upstream\n\tcontrolRpc := router.GetControlRpc()\n\n\t// authenticate with the upstream router using the JWT\n\t_, err = wshclient.AuthenticateCommand(controlRpc, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRootRoute})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error authenticating with upstream: %v\", err)\n\t}\n\tlog.Printf(\"authenticated with upstream router\")\n\n\t// fetch and set JWT public key\n\tlog.Printf(\"trying to get JWT public key\")\n\tjwtPublicKeyB64, err := wshclient.GetJwtPublicKeyCommand(controlRpc, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting jwt public key: %v\", err)\n\t}\n\tjwtPublicKeyBytes, err := base64.StdEncoding.DecodeString(jwtPublicKeyB64)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error decoding jwt public key: %v\", err)\n\t}\n\terr = wavejwt.SetPublicKey(jwtPublicKeyBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting jwt public key: %v\", err)\n\t}\n\tlog.Printf(\"got JWT public key\")","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-connserver.go#L325-L361","documentation":"This wraps the failure of wshclient.AuthenticateCommand, which sends the JWT to the upstream router's control RPC (ControlRootRoute) to authenticate the domain-socket connection. Failure means the upstream rejected the token (bad signature, expired, wrong audience) or the RPC itself failed, so the connserver refuses to continue without verified credentials.","triggerScenarios":"wshclient.AuthenticateCommand(controlRpc, jwtToken, {Route: ControlRootRoute}) returns an error — the upstream router denied the JWT or the RPC timed out/disconnected.","commonSituations":"Clock skew making the JWT appear expired; JWT generated by a different Wave install with different signing keys; stale token reused after the server restarted with new secrets; upstream dropped the connection mid-RPC.","solutions":["Restart the wsh connserver so it gets a fresh JWT from the Wave terminal environment.","Check system clock skew (NTP) between client and server.","Ensure wsh and Wave server are the same version (signing/verification changes between releases).","Look at the wrapped %v: 'token expired' → new token; 'signature invalid' → version/key mismatch; 'connection closed' → upstream socket died.","Remove stale socket files and restart both Wave server and wsh connserver."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before authenticating, sanity-check token expiry (unverified)\nparts := strings.Split(jwtToken, \".\")\nif len(parts) == 3 {\n\tif raw, err := base64.RawURLEncoding.DecodeString(parts[1]); err == nil {\n\t\tvar c struct{ Exp int64 `json:\"exp\"` }\n\t\tif json.Unmarshal(raw, &c) == nil && c.Exp != 0 && time.Now().Unix() > c.Exp {\n\t\t\treturn errors.New(\"jwt already expired; get a fresh token\")\n\t\t}\n\t}\n}","typeGuard":null,"tryCatchPattern":"_, err = wshclient.AuthenticateCommand(controlRpc, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRootRoute})\nif err != nil {\n\treturn fmt.Errorf(\"error authenticating with upstream: %w\", err)\n}","preventionTips":["Sync clocks via NTP to avoid spurious expiry.","Always use a freshly issued JWT per session.","Match client/server versions (signing keys/algorithms).","Retry once on transient transport errors, but fail fast on signature/expiry errors."],"tags":["jwt","authentication","rpc","security"],"backgroundTag":"jwt-authentication-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}