{"record":{"id":"a6a64dfc5c88ca9c","repo":"wavetermdev/waveterm","slug":"error-generating-jwt-keypair-w","errorCode":null,"errorMessage":"error generating jwt keypair: %w","messagePattern":"error generating jwt keypair: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wcore/wcore.go","lineNumber":185,"sourceCode":"\n\tmainServer, err := wstore.DBGetSingleton[*waveobj.MainServer](ctx)\n\tif err == wstore.ErrNotFound {\n\t\tmainServer = &waveobj.MainServer{\n\t\t\tOID: uuid.NewString(),\n\t\t}\n\t\terr = wstore.DBInsert(ctx, mainServer)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error inserting mainserver: %w\", err)\n\t\t}\n\t} else if err != nil {\n\t\treturn fmt.Errorf(\"error getting mainserver: %w\", err)\n\t}\n\n\tneedsUpdate := false\n\tif mainServer.JwtPrivateKey == \"\" || mainServer.JwtPublicKey == \"\" {\n\t\tkeyPair, err := wavejwt.GenerateKeyPair()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error generating jwt keypair: %w\", err)\n\t\t}\n\t\tmainServer.JwtPrivateKey = base64.StdEncoding.EncodeToString(keyPair.PrivateKey)\n\t\tmainServer.JwtPublicKey = base64.StdEncoding.EncodeToString(keyPair.PublicKey)\n\t\tneedsUpdate = true\n\t}\n\n\tif needsUpdate {\n\t\terr = wstore.DBUpdate(ctx, mainServer)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error updating mainserver: %w\", err)\n\t\t}\n\t}\n\n\tprivateKeyBytes, err := base64.StdEncoding.DecodeString(mainServer.JwtPrivateKey)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error decoding jwt private key: %w\", err)\n\t}\n\tpublicKeyBytes, err := base64.StdEncoding.DecodeString(mainServer.JwtPublicKey)","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wcore/wcore.go#L167-L203","documentation":"InitMainServer generates a new ed25519 key pair via wavejwt.GenerateKeyPair when the MainServer singleton has no stored JWT keys. If key generation fails, this error wraps the cause and aborts startup. Key generation on a modern host essentially never fails except under extreme resource exhaustion.","triggerScenarios":"First run (or after keys were cleared) where MainServer.JwtPrivateKey or JwtPublicKey is empty and crypto/rand's ed25519.GenerateKey returns an error — e.g. the OS entropy source (/dev/urandom) is unavailable or the process is severely resource-starved.","commonSituations":"Running in a hardened/sandboxed container with restricted access to the kernel RNG; extreme memory pressure; exotic platforms with broken crypto/rand.","solutions":["Check the wrapped cause in logs; if it is a crypto/rand failure, verify /dev/urandom is accessible inside the container/sandbox","Restart the process — key generation is transient and typically succeeds on retry","Confirm Go runtime and OS are supported; update to a current Go/app version","Check system memory and resource limits (ulimit, cgroup limits)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// ensure entropy source is available (Linux)\nif _, err := os.Stat(\"/dev/urandom\"); err != nil {\n    log.Fatal(\"crypto entropy source unavailable\")\n}","typeGuard":null,"tryCatchPattern":"err := wcore.InitMainServer()\nfor i := 0; err != nil && i < 3; i++ {\n    time.Sleep(time.Duration(i+1) * 200 * time.Millisecond)\n    err = wcore.InitMainServer()\n}\nif err != nil { log.Fatalf(\"init: %v\", err) }","preventionTips":["Do not restrict /dev/urandom access in containers running the app","Provide adequate memory/entropy on first-run environments","Expect first run to generate keys; pre-seed valid keys only via supported config","Keep Go runtime updated for crypto/rand fixes"],"tags":["jwt","cryptography","keypair","startup"],"backgroundTag":"key-generation-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}