{"record":{"id":"0c9aa765fc6756fd","repo":"wavetermdev/waveterm","slug":"failed-to-validate-token-w","errorCode":null,"errorMessage":"failed to validate token: %w","messagePattern":"failed to validate token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobmanager/mainserverconn.go","lineNumber":75,"sourceCode":"\t\tJobAuthToken: jobAuthToken,\n\t}\n\terr := wshclient.AuthenticateJobManagerCommand(msc.WshRpc, authData, &wshrpc.RpcOpts{Route: wshutil.ControlRoute})\n\tif err != nil {\n\t\tlog.Printf(\"authenticateSelfToServer: failed to authenticate to server: %v\\n\", err)\n\t\treturn fmt.Errorf(\"failed to authenticate to server: %w\", err)\n\t}\n\tmsc.SelfAuthenticated.Store(true)\n\tlog.Printf(\"authenticateSelfToServer: successfully authenticated to server\\n\")\n\treturn nil\n}\n\nfunc (msc *MainServerConn) AuthenticateToJobManagerCommand(ctx context.Context, data wshrpc.CommandAuthenticateToJobData) error {\n\tjobId, jobAuthToken := WshCmdJobManager.GetJobAuthInfo()\n\n\tclaims, err := wavejwt.ValidateAndExtract(data.JobAccessToken)\n\tif err != nil {\n\t\tlog.Printf(\"AuthenticateToJobManager: failed to validate token: %v\\n\", err)\n\t\treturn fmt.Errorf(\"failed to validate token: %w\", err)\n\t}\n\tif !claims.MainServer {\n\t\tlog.Printf(\"AuthenticateToJobManager: MainServer claim not set\\n\")\n\t\treturn fmt.Errorf(\"MainServer claim not set\")\n\t}\n\tif claims.JobId != jobId {\n\t\tlog.Printf(\"AuthenticateToJobManager: JobId mismatch: expected %s, got %s\\n\", jobId, claims.JobId)\n\t\treturn fmt.Errorf(\"JobId mismatch\")\n\t}\n\tmsc.PeerAuthenticated.Store(true)\n\tlog.Printf(\"AuthenticateToJobManager: authentication successful for JobId=%s\\n\", claims.JobId)\n\n\terr = msc.authenticateSelfToServer(jobAuthToken)\n\tif err != nil {\n\t\tmsc.PeerAuthenticated.Store(false)\n\t\treturn err\n\t}\n","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/mainserverconn.go#L57-L93","documentation":"During peer authentication, the incoming JobAccessToken presented by the connecting party is validated with wavejwt.ValidateAndExtract; if the JWT is invalid (bad signature, expired, malformed), this error wraps the JWT library error. The server rejects the connection before any job commands are allowed.","triggerScenarios":"AuthenticateToJobManagerCommand receives data.JobAccessToken that fails wavejwt.ValidateAndExtract — expired token, signed by the wrong key, or structurally malformed JWT.","commonSituations":"Stale access tokens after server key rotation, clock skew between machines causing premature expiry, copying an old token, or truncated tokens from manual copy/paste.","solutions":["Obtain a fresh JobAccessToken from the main server and retry the authentication.","Verify both sides share the same JWT signing secret/key and that clocks are synced (NTP).","Decode the wrapped error to see the JWT cause (expired vs signature) and fix accordingly."],"exampleFix":"// before\nclaims, err := wavejwt.ValidateAndExtract(data.JobAccessToken)\n// after\nif claims, err := wavejwt.ValidateAndExtract(data.JobAccessToken); err != nil {\n    return fmt.Errorf(\"token invalid (%v); request a fresh JobAccessToken from the main server\", err)\n} else { _ = claims }","handlingStrategy":"validation","validationCode":"parts := strings.Split(data.JobAccessToken, \".\")\nif len(parts) != 3 {\n    return fmt.Errorf(\"malformed JobAccessToken: must be a 3-part JWT\")\n}","typeGuard":null,"tryCatchPattern":"if err := conn.AuthenticateToJobManagerCommand(ctx, authData); err != nil {\n    if strings.Contains(err.Error(), \"failed to validate token\") {\n        authData.JobAccessToken = fetchFreshToken()\n        err = conn.AuthenticateToJobManagerCommand(ctx, authData)\n    }\n    if err != nil { return err }\n}","preventionTips":["Refresh tokens before expiry instead of caching indefinitely","Sync clocks via NTP on all hosts","Never hand-edit or truncate JWTs"],"tags":["jwt","authentication","token-expired","security"],"backgroundTag":"jwt-token-expired","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}