{"record":{"id":"e76572a40d4489bf","repo":"wavetermdev/waveterm","slug":"failed-to-set-public-key-w","errorCode":null,"errorMessage":"failed to set public key: %w","messagePattern":"failed to set public key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/jobmanager/jobmanager.go","lineNumber":60,"sourceCode":"\tlock                  sync.Mutex\n\tattachedClient        *MainServerConn\n\tconnectedStreamClient *MainServerConn\n\tpendingStreamMeta     *wshrpc.StreamMeta\n}\n\nfunc SetupJobManager(clientId string, jobId string, publicKeyBytes []byte, jobAuthToken string, readyFile *os.File) error {\n\tif runtime.GOOS != \"linux\" && runtime.GOOS != \"darwin\" {\n\t\treturn fmt.Errorf(\"job manager only supported on unix systems, not %s\", runtime.GOOS)\n\t}\n\tWshCmdJobManager.ClientId = clientId\n\tWshCmdJobManager.JobId = jobId\n\tWshCmdJobManager.JwtPublicKey = publicKeyBytes\n\tWshCmdJobManager.JobAuthToken = jobAuthToken\n\tWshCmdJobManager.StreamManager = MakeStreamManager()\n\tWshCmdJobManager.InputQueue = utilds.MakeQuickReorderQueue[wshrpc.CommandJobInputData](JobInputQueueSize, JobInputQueueTimeout)\n\terr := wavejwt.SetPublicKey(publicKeyBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set public key: %w\", err)\n\t}\n\terr = MakeJobDomainSocket(clientId, jobId)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"JobManager:processInputQueue\", recover())\n\t\t}()\n\t\tWshCmdJobManager.processInputQueue()\n\t}()\n\n\tfmt.Fprintf(readyFile, JobManagerStartLabel+\"\\n\")\n\treadyFile.Close()\n\n\terr = daemonize(clientId, jobId)\n\tif err != nil {","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/jobmanager.go#L42-L78","documentation":"SetupJobManager installs the JWT public key used to authenticate job stream requests by calling wavejwt.SetPublicKey. If that fails (e.g. the key bytes are malformed or the JWT library rejects them), this error wraps the underlying cause and aborts job manager setup.","triggerScenarios":"publicKeyBytes are empty, truncated, or not a valid PEM/ed25519 public key; key generated by a mismatched algorithm or corrupted in transit; SetPublicKey called twice with incompatible state.","commonSituations":"Auth token/public key serialized incorrectly between the main server and the job manager daemon process; an upgraded key format (algorithm change) not matching what wavejwt expects; a copied key file missing its last bytes.","solutions":["Regenerate/verify the public key bytes and confirm they are the exact bytes the server signed the job JWT with","Check the wrapped error from wavejwt.SetPublicKey to see whether it is a parse vs state problem","Ensure the key is passed intact across the exec boundary (files/hex/base64, not env truncation)","Confirm client and server are the same Wave version so key formats match"],"exampleFix":"// before\npub, _ := os.ReadFile(keyPath)\nSetupJobManager(cid, jid, pub, token, rf) // possibly empty/partial\n// after\npub, err := os.ReadFile(keyPath)\nif err != nil || len(pub) == 0 {\n    return fmt.Errorf(\"missing or empty public key file %s\", keyPath)\n}\nSetupJobManager(cid, jid, pub, token, rf)","handlingStrategy":"validation","validationCode":"if len(publicKeyBytes) == 0 {\n    return fmt.Errorf(\"public key is empty\")\n}\nif _, err := wavejwt.ParsePublicKey(publicKeyBytes); err != nil {\n    return fmt.Errorf(\"malformed public key: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := jobmanager.SetupJobManager(cid, jid, pub, tok, rf); err != nil {\n    if strings.Contains(err.Error(), \"failed to set public key\") {\n        // regenerate key material / re-fetch from server, then retry setup once\n        return\n    }\n    return err\n}","preventionTips":["Pass key bytes verbatim (base64/hex) across process boundaries, not raw env strings","Keep client and server on matching versions so key formats agree","Validate key parseability before daemon launch","Log key length (not contents) on failure for diagnosis"],"tags":["jwt","public-key","auth"],"backgroundTag":"invalid-public-key","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}