{"record":{"id":"5c76fae700929275","repo":"clockworklabs/SpacetimeDB","slug":"no-fingerprint-saved-for-server","errorCode":null,"errorMessage":"No fingerprint saved for server: {}","messagePattern":"No fingerprint saved for server: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/config.rs","lineNumber":759,"sourceCode":"        // (see https://github.com/clockworklabs/SpacetimeDB/pull/1341#issuecomment-2150857432).\n        if let Err(e) = atomic_write(&home_path.0, config) {\n            eprintln!(\"Could not save config file: {e}\")\n        }\n    }\n\n    pub fn server_decoding_key(&self, server: Option<&str>) -> anyhow::Result<DecodingKey> {\n        self.server_fingerprint(server).and_then(|fing| {\n            if let Some(fing) = fing {\n                DecodingKey::from_ec_pem(fing.as_bytes()).with_context(|| {\n                    format!(\n                        \"Unable to parse invalid saved server fingerprint as ECDSA public key.\nUpdate the server's fingerprint with:\n\\tspacetime server fingerprint {}\",\n                        server.unwrap_or(\"\")\n                    )\n                })\n            } else {\n                Err(anyhow::anyhow!(\n                    \"No fingerprint saved for server: {}\",\n                    self.server_nick_or_host(server)?,\n                ))\n            }\n        })\n    }\n\n    pub fn server_nick_or_host<'a>(&'a self, server: Option<&'a str>) -> anyhow::Result<&'a str> {\n        if let Some(server) = server {\n            let (host, _) = host_or_url_to_host_and_protocol(server);\n            Ok(host)\n        } else {\n            self.home.default_server().map(ServerConfig::nick_or_host)\n        }\n    }\n\n    pub fn server_fingerprint(&self, server: Option<&str>) -> anyhow::Result<Option<&str>> {\n        if let Some(server) = server {","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/cli/src/config.rs#L741-L777","documentation":"server_decoding_key builds a JWT DecodingKey from the server's pinned ECDSA public key. Here server_fingerprint resolved the server's config entry, but its ecdsa_public_key field is None, so there is nothing to build a key from and token verification cannot proceed. Fingerprints are saved when the CLI pins a server's identity; an entry created by `server add` starts without one. The sibling error in the same function handles the 'fingerprint exists but is invalid PEM' case and suggests `spacetime server fingerprint <server>`.","triggerScenarios":"Any operation that verifies server tokens (login/logout flows, authenticated requests that check the server's identity) against a server whose config entry exists but never had a fingerprint stored — e.g. added via `spacetime server add` and never connected to, or the fingerprint was cleared.","commonSituations":"Freshly added server before first successful connection; config edited by hand and the key field dropped; CI environment provisioned by copying a config that was saved before the first login; server re-provisioned with a new key and the stale entry recreated empty.","solutions":["Fetch and store the fingerprint explicitly: `spacetime server fingerprint <server>`","Re-login against the server (`spacetime login --server <server>`) so the CLI connects and persists the server's public key","Inspect `spacetime server list` / the config file to confirm which entries lack a fingerprint before scripting dependent commands"],"exampleFix":"# before\nspacetime publish --server myserver mydb   # error: No fingerprint saved for server: myserver\n\n# after\nspacetime server fingerprint myserver\nspacetime publish --server myserver mydb","handlingStrategy":"try-catch","validationCode":"# Ensure a fingerprint is pinned before running token-verified commands\nspacetime server fingerprint \"$SERVER\" || spacetime login --server \"$SERVER\"","typeGuard":null,"tryCatchPattern":"match config.server_decoding_key(Some(server)) {\n    Ok(key) => key,\n    Err(e) if e.to_string().starts_with(\"No fingerprint saved for server\") => {\n        // remediate: fetch and store the server's public key, then retry once\n        run!(\"spacetime\", [\"server\", \"fingerprint\", server])?;\n        config.server_decoding_key(Some(server))?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["After any `spacetime server add`, immediately run `spacetime server fingerprint <name>` (or a login) so the entry is complete","When copying CLI configs to CI, verify the entry carries an ecdsa_public_key before depending on token verification"],"tags":["spacetimedb","cli","fingerprint","ecdsa","jwt","auth"],"backgroundTag":"missing-server-fingerprint","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}