clockworklabs/SpacetimeDB · error
Issuer empty
Error message
Issuer empty
What it means
SpacetimeDB requires JWTs to carry a non-empty iss claim (crates/auth/src/identity.rs:110) because the identity is computed from iss and sub together; an empty issuer cannot derive a valid identity, so claim conversion fails immediately.
Source
Thrown at crates/auth/src/identity.rs:110
/// All remaining claims from the JWT payload
#[serde(flatten)]
pub extra: Option<HashMap<Box<str>, serde_json::Value>>,
}
impl TryInto<SpacetimeIdentityClaims> for IncomingClaims {
type Error = anyhow::Error;
fn try_into(self) -> anyhow::Result<SpacetimeIdentityClaims> {
// The issuer and subject must be less than 128 bytes.
if self.issuer.len() > 128 {
return Err(anyhow::anyhow!("Issuer too long: {:?}", self.issuer));
}
if self.subject.len() > 128 {
return Err(anyhow::anyhow!("Subject too long: {:?}", self.subject));
}
// The issuer and subject must be non-empty.
if self.issuer.is_empty() {
return Err(anyhow::anyhow!("Issuer empty"));
}
if self.subject.is_empty() {
return Err(anyhow::anyhow!("Subject empty"));
}
let computed_identity = Identity::from_claims(&self.issuer, &self.subject);
// If an identity is provided, it must match the computed identity.
if let Some(token_identity) = self.identity
&& token_identity != computed_identity
{
return Err(anyhow::anyhow!(
"Identity mismatch: token identity {token_identity:?} does not match computed identity {computed_identity:?}",
));
}
Ok(SpacetimeIdentityClaims {
identity: computed_identity,
subject: self.subject,View on GitHub (pinned to 524b4487d9)
Solutions
- Ensure the token includes a non-empty iss claim (at most 128 bytes)
- Fix the token-minting code or provider config that drops iss
- Regenerate test fixtures/tokens with the full standard claim set
Example fix
// before (JWT payload)
{ "sub": "12345" }
// after
{ "iss": "https://identity.example.com", "sub": "12345" } Defensive patterns
Strategy: validation
Validate before calling
// Reject tokens with empty/missing iss before authentication:
const claims = decodeJwtPayload(token); // your decoder
if (typeof claims.iss !== 'string' || claims.iss.length === 0) {
throw new Error('Token rejected: iss claim missing or empty');
} Type guard
function hasIssuer(claims: Record<string, unknown>): claims is { iss: string } {
return typeof claims.iss === 'string' && claims.iss.length > 0;
} Prevention
- Require the standard iss claim in token-minting templates
- Validate decoded claims in tests, not just signatures
- Avoid proxies that rewrite/drop claims
When it happens
Trigger: Authenticating with a token where iss is absent (deserialization leaves it empty) or explicitly the empty string; tokens minted by test tooling that omits standard claims.
Common situations: Hand-rolled JWT minting that forgets iss; test/dev tokens signed with only sub; upstream proxy stripping the iss claim while rewriting tokens.
Related errors
- Issuer too long: {:?}
- Subject too long: {:?}
- Subject empty
- Identity mismatch: token identity {token_identity:?} does no
- No fingerprint saved for server: {}
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/ad44e6e3e0834946.
Report an issue: GitHub.