{"record":{"id":"257c7fff60e5e4f4","repo":"wavetermdev/waveterm","slug":"no-jobauthtoken-in-authenticatejobmanager-message","errorCode":null,"errorMessage":"no jobauthtoken in authenticatejobmanager message","messagePattern":"no jobauthtoken in authenticatejobmanager message","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":226,"sourceCode":"\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\")\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 {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L208-L244","documentation":"The AuthenticateJobManagerVerify RPC payload must include the JobAuthToken secret to compare against the stored job record. An empty JobAuthToken can never match, so the command rejects it up front before touching the database.","triggerScenarios":"Sending Command_AuthenticateJobManagerVerify with CommandAuthenticateJobManagerData{JobAuthToken: \"\"} — token never loaded from the job record, zero-value struct, or the field was dropped in serialization.","commonSituations":"Client lost the job secret (e.g. reading from a different job record or a cleared cache); building the data struct partially; environment where the job manager hands off only the job id.","solutions":["Populate data.JobAuthToken from the job's stored secret before calling the RPC.","Verify the source of the token (config/env/job record) is actually returning a value.","Validate the payload before sending the RPC to fail fast.","Check serialization so the jobauthtoken field is not dropped."],"exampleFix":"// before\n_, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, wshrpc.CommandAuthenticateJobManagerData{JobId: id}, opts)\n// after\nif data.JobAuthToken == \"\" {\n    return fmt.Errorf(\"cannot verify job: JobAuthToken is empty\")\n}\n_, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, data, opts)","handlingStrategy":"validation","validationCode":"if data.JobAuthToken == \"\" {\n    return fmt.Errorf(\"JobAuthToken is required for job-manager verification\")\n}\n// safe to call RPC","typeGuard":"func jobDataComplete(d wshrpc.CommandAuthenticateJobManagerData) bool {\n    return d.JobId != \"\" && d.JobAuthToken != \"\"\n}","tryCatchPattern":"err := verifyJobManager(ctx, data)\nif err != nil && strings.Contains(err.Error(), \"no jobauthtoken in authenticatejobmanager message\") {\n    return fmt.Errorf(\"caller bug: JobAuthToken was never loaded: %w\", err)\n}","preventionTips":["Load the token from the job creation response and fail fast if empty.","Never build the auth struct partially; use a single constructor.","Add a pre-send validation helper for auth payloads."],"tags":["validation","rpc","authentication"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}