{"record":{"id":"bd7a3bc35e01063c","repo":"wavetermdev/waveterm","slug":"invalid-jobauthtoken","errorCode":null,"errorMessage":"invalid jobauthtoken","messagePattern":"invalid jobauthtoken","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":237,"sourceCode":"\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\")\n\t}\n\n\tlog.Printf(\"wshrouter authenticate-jobmanager-verify success jobid=%q\", data.JobId)\n\treturn nil\n}\n\nfunc (impl *WshRouterControlImpl) AuthenticateJobManagerCommand(ctx context.Context, data wshrpc.CommandAuthenticateJobManagerData) error {\n\thandler := GetRpcResponseHandlerFromContext(ctx)\n\tif handler == nil {\n\t\treturn fmt.Errorf(\"no response handler in context\")\n\t}\n\tlinkId := handler.GetIngressLinkId()\n\tif linkId == baseds.NoLinkId {\n\t\treturn fmt.Errorf(\"no ingress link found\")\n\t}\n\n\tif data.JobId == \"\" {\n\t\treturn fmt.Errorf(\"no jobid in authenticatejobmanager message\")","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L219-L255","documentation":"The job record was found, but the supplied JobAuthToken does not equal the job.JobAuthToken stored in the database. This is a deliberate authentication failure: the caller presented the wrong (or stale) secret for the job and the router refuses to trust the link for that job.","triggerScenarios":"AuthenticateJobManagerVerify / AuthenticateJobManager called with a JobAuthToken that mismatches the stored job.JobAuthToken — stale token after job re-creation, token from a different job, or a client that cached an old secret.","commonSituations":"Job recreated (new random token) but the client still holds the previous token; multiple environments sharing job ids with different secrets; secret truncated or altered in transit/config.","solutions":["Re-fetch the current job record / token from the authoritative source (the root that owns the job) and retry with the fresh token.","If the job was recreated, re-register with the new token instead of the cached one.","Verify no config or copy step truncates/transforms the token string.","Confirm the JobId and JobAuthToken come from the same job creation response."],"exampleFix":"// before\n_, err = jobClient.Verify(wshrpc.CommandAuthenticateJobManagerData{JobId: cachedJobId, JobAuthToken: cachedToken})\n// after\njob, err := jobClient.Get(cachedJobId)\nif err != nil { return err }\n_, err = jobClient.Verify(wshrpc.CommandAuthenticateJobManagerData{JobId: cachedJobId, JobAuthToken: job.JobAuthToken})","handlingStrategy":"validation","validationCode":"// fetch the authoritative token instead of using a cached one\njob, err := jobStore.Get(ctx, data.JobId)\nif err != nil { return err }\nif job.JobAuthToken != data.JobAuthToken {\n    data.JobAuthToken = job.JobAuthToken // refresh stale secret before verifying\n}","typeGuard":null,"tryCatchPattern":"err := verifyJobManager(ctx, data)\nif err != nil && strings.Contains(err.Error(), \"invalid jobauthtoken\") {\n    // do not retry blindly: refresh the token from the authoritative job record first\n    return refreshJobTokenAndRetry(ctx, data.JobId)\n}","preventionTips":["Never cache job auth tokens across job re-creation cycles.","Keep JobId and JobAuthToken from the same creation response.","Treat this error as a security signal — log it but never fall back to unverified operation."],"tags":["authentication","security","secret-mismatch"],"backgroundTag":"auth-token-mismatch","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}