clockworklabs/SpacetimeDB · error · anyhow::Error
Issuer too long: {:?}
Error message
Issuer too long: {:?} What it means
When converting incoming JWT claims into SpacetimeIdentityClaims (crates/auth/src/identity.rs:103), SpacetimeDB requires the iss claim to be at most 128 bytes. The identity is derived by hashing iss+sub into a fixed-size Identity, so oversized issuers are rejected outright.
Source
Thrown at crates/auth/src/identity.rs:103
/// The unix timestamp the token was issued at
#[serde_as(as = "serde_with::TimestampSeconds")]
pub iat: SystemTime,
#[serde_as(as = "Option<serde_with::TimestampSeconds>")]
pub exp: Option<SystemTime>,
/// 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!(View on GitHub (pinned to 524b4487d9)
Solutions
- Shorten the issuer string to 128 bytes or fewer (compact identifier or bare URL without query parameters)
- Reconfigure the identity provider to emit the short form of its issuer
- If you mint tokens yourself, keep iss minimal and put extra metadata in custom claims
Example fix
// before (JWT payload)
{ "iss": "https://identity.internal.example.com/realms/master/protocol/openid-connect/?env=prod", ... }
// after
{ "iss": "https://identity.example.com/master", ... } Defensive patterns
Strategy: validation
Validate before calling
// Before sending a token to SpacetimeDB, check iss:
function assertIssuerOk(jwt: { iss: string }) {
const bytes = new TextEncoder().encode(jwt.iss).length;
if (bytes === 0) throw new Error('iss must be non-empty');
if (bytes > 128) throw new Error(`iss is ${bytes} bytes; max is 128`);
} Type guard
function hasValidSpacetimeIssuer(claims: Record<string, unknown>): claims is { iss: string } {
const iss = claims.iss;
return typeof iss === 'string' && iss.length > 0 && iss.length <= 128;
} Prevention
- Keep issuer identifiers short and stable from day one
- Validate iss length in your token-minting tests
- Never put environment metadata or query strings in iss
When it happens
Trigger: Authenticating with a token whose iss claim exceeds 128 bytes — e.g. a long OIDC issuer URL with paths, ports, and query strings — during token exchange / spacetime login against a custom identity provider.
Common situations: Custom JWT providers (Auth0, Keycloak, self-hosted) configured with verbose issuer URLs; tokens minted by internal tooling that stuffs parameters into iss; issuer URLs that grew when moving environments or regions.
Related errors
- Subject too long: {:?}
- Issuer empty
- 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/afa358d4e85a5f62.
Report an issue: GitHub.