{"record":{"id":"701955dd1c213a5f","repo":"clockworklabs/SpacetimeDB","slug":"unable-to-read-public-key-for-jwt-token-verificati","errorCode":null,"errorMessage":"Unable to read public key for JWT token verification","messagePattern":"Unable to read public key for JWT token verification","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/core/src/auth/mod.rs","lineNumber":65,"sourceCode":"\n// Get the key pair if the given files exist. If they don't, create them.\n// If only one of the files exists, return an error.\npub fn get_or_create_keys(certs: &CertificateAuthority) -> anyhow::Result<JwtKeys> {\n    let public_key_path = &certs.jwt_pub_key_path;\n    let private_key_path = &certs.jwt_priv_key_path;\n\n    let public_key_bytes = public_key_path.read().ok();\n    let private_key_bytes = private_key_path.read().ok();\n\n    // If both keys are unspecified, create them\n    let key_pair = match (public_key_bytes, private_key_bytes) {\n        (Some(pub_), Some(priv_)) => EcKeyPair::new(pub_, priv_),\n        (None, None) => {\n            let keys = EcKeyPair::generate()?;\n            keys.write_to_files(public_key_path, private_key_path)?;\n            keys\n        }\n        (None, Some(_)) => anyhow::bail!(\"Unable to read public key for JWT token verification\"),\n        (Some(_), None) => anyhow::bail!(\"Unable to read private key for JWT token signing\"),\n    };\n\n    key_pair.try_into()\n}\n\n// An Ec key pair in pem format.\npub struct EcKeyPair {\n    pub public_key_bytes: Vec<u8>,\n    pub private_key_bytes: Vec<u8>,\n}\n\nimpl TryFrom<EcKeyPair> for JwtKeys {\n    type Error = anyhow::Error;\n    fn try_from(pair: EcKeyPair) -> anyhow::Result<Self> {\n        JwtKeys::new(pair.public_key_bytes, pair.private_key_bytes)\n    }\n}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/core/src/auth/mod.rs#L47-L83","documentation":"At startup the node reads its EC key pair for JWT signing/verification from the keychain files. The pair must both exist or both be absent (in which case a fresh pair is generated and written); if the private key file is readable but the public key file is missing or unreadable, startup aborts with this error before serving any traffic.","triggerScenarios":"Deleting, moving, or truncating only the public key file in the keychain directory; a partial backup restore that copied the private key but not the public key; permission or filesystem damage affecting just one of the two files.","commonSituations":"Hand-cleaning or rotating key directories; backup scripts that glob only private keys; copying keychain dirs between hosts incompletely; container volumes where one key file was overwritten.","solutions":["Restore the matching public key from backup so the pair is consistent again.","Or delete BOTH key files and restart — the node generates a fresh pair; note all previously issued tokens become invalid and users must re-login.","Check file permissions on both key files in the keychain directory.","Never regenerate only one side — EC keys must be a matched pair."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# pre-start: key pair must be all-present or all-absent\nKEYDIR=\"$STDB_KEYCHAIN_DIR\"\npub=\"$KEYDIR/public.pem\"; priv=\"$KEYDIR/private.pem\"   # adjust to your keychain layout\nif [ -f \"$priv\" ] && [ ! -f \"$pub\" ]; then\n  echo \"JWT key pair incomplete — restore public key or delete BOTH keys to regenerate\" >&2; exit 1;\nfi\nexec spacetime start","typeGuard":null,"tryCatchPattern":"Wrap server startup and abort the deployment (fail fast) when stderr contains 'Unable to read public key'; alert the operator instead of looping restarts.","preventionTips":["Back up the key pair together, never one file.","Do not hand-edit or partially delete keychain directories.","Persist the whole keychain dir as one container volume."],"tags":["spacetimedb","server","auth","keys","startup","jwt"],"backgroundTag":"missing-key-file","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}