{"record":{"id":"955cf4c0b56d1676","repo":"wavetermdev/waveterm","slug":"error-setting-jwt-public-key-v","errorCode":null,"errorMessage":"error setting jwt public key: %v","messagePattern":"error setting jwt public key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-connserver.go","lineNumber":259,"sourceCode":"\t\treturn fmt.Errorf(\"error setting up connserver rpc client: %v\", err)\n\t}\n\twshfs.RpcClient = client\n\twshfs.RpcClientRouteId = bareRouteId\n\n\tlog.Printf(\"trying to get JWT public key\")\n\n\t// fetch and set JWT public key\n\tjwtPublicKeyB64, err := wshclient.GetJwtPublicKeyCommand(client, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting jwt public key: %v\", err)\n\t}\n\tjwtPublicKeyBytes, err := base64.StdEncoding.DecodeString(jwtPublicKeyB64)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error decoding jwt public key: %v\", err)\n\t}\n\terr = wavejwt.SetPublicKey(jwtPublicKeyBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting jwt public key: %v\", err)\n\t}\n\n\tlog.Printf(\"got JWT public key\")\n\n\t// now set up the domain socket\n\tunixListener, err := MakeRemoteUnixListener()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot create unix listener: %v\", err)\n\t}\n\tlog.Printf(\"unix listener started\")\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"serverRunRouter:runListener\", recover())\n\t\t}()\n\t\trunListener(unixListener, router)\n\t}()\n\t// run the sysinfo loop\n\tgo func() {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-connserver.go#L241-L277","documentation":"This error is wrapped by serverRunRouter when wavejwt.SetPublicKey fails after the base64-encoded JWT public key was fetched from the upstream connserver over the stdio-based router. SetPublicKey rejects keys that are not a valid public key it can parse (e.g. not PEM/DER-encoded RSA or ECDSA material), so the remote connection cannot proceed with JWT verification. The wrapped %v carries the underlying key-parsing error.","triggerScenarios":"wsh connserver run in router mode (upstream over stdin/stdout) calls GetJwtPublicKeyCommand, base64-decodes it successfully, then wavejwt.SetPublicKey(jwtPublicKeyBytes) returns an error because the bytes are not a parseable public key.","commonSituations":"Version mismatch between wsh client and waveterm server where the key format changed; a corrupted or truncated key in transit; a stub/mock upstream returning garbage for GetJwtPublicKey; hand-edited JWT key configuration.","solutions":["Check wsh and waveterm server versions match (upgrade both to the same release).","Log the base64 key before decoding and verify it decodes to valid PEM public key material.","Re-run the connection so GetJwtPublicKeyCommand returns a fresh key from the real upstream.","If running a custom/proxy upstream, return the exact key bytes produced by the server's JWT signer."],"exampleFix":"// before\njwtPublicKeyBytes, err := base64.StdEncoding.DecodeString(jwtPublicKeyB64)\nif err != nil {\n\treturn fmt.Errorf(\"error decoding jwt public key: %v\", err)\n}\n// after\njwtPublicKeyBytes, err := base64.StdEncoding.DecodeString(jwtPublicKeyB64)\nif err != nil {\n\treturn fmt.Errorf(\"error decoding jwt public key: %v\", err)\n}\nlog.Printf(\"jwt public key (b64, len=%d): %s\", len(jwtPublicKeyB64), jwtPublicKeyB64) // inspect payload\nif err := wavejwt.SetPublicKey(jwtPublicKeyBytes); err != nil {\n\treturn fmt.Errorf(\"error setting jwt public key (key bytes=%d): %w\", len(jwtPublicKeyBytes), err)\n}","handlingStrategy":"validation","validationCode":"decoded, err := base64.StdEncoding.DecodeString(jwtPublicKeyB64)\nif err != nil || len(decoded) == 0 {\n\treturn fmt.Errorf(\"bad jwt public key payload\")\n}\nif !bytes.Contains(decoded, []byte(\"PUBLIC KEY\")) {\n\treturn fmt.Errorf(\"payload is not PEM public key material\")\n}","typeGuard":"func isValidPublicKeyPem(b []byte) bool {\n\tblock, _ := pem.Decode(b)\n\treturn block != nil && strings.HasSuffix(block.Type, \"PUBLIC KEY\")\n}","tryCatchPattern":"if err := wavejwt.SetPublicKey(keyBytes); err != nil {\n\treturn fmt.Errorf(\"error setting jwt public key: %w\", err)\n}","preventionTips":["Keep wsh and the Wave server on identical versions.","Log the base64 key payload when debugging key errors.","Never hand-edit or truncate JWT key configuration.","Verify keys with openssl pkey -pubin before deploying custom upstreams."],"tags":["jwt","crypto","public-key","remote-connection"],"backgroundTag":"invalid-jwt-public-key","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}