clockworklabs/SpacetimeDB · error · DatastoreError

Failed to get JWT payload for connection id ({connection_id}

Error message

Failed to get JWT payload for connection id ({connection_id}): {e}

What it means

get_jwt_payload scans st_connection_credentials by connection_id and BSATN-decodes each matching row to extract jwt_payload. This error fires only when that read/decode step fails — a missing row returns Ok(None) instead — i.e. the stored credential row's bytes do not match the expected st_connection_credentials row shape (system-table schema drift or corrupted storage).

Source

Thrown at crates/datastore/src/locking_tx_datastore/state_view.rs:329

    }

    fn get_jwt_payload(&self, connection_id: ConnectionId) -> Result<Option<String>> {
        log::trace!("Getting JWT payload for connection id: {}", connection_id.to_hex());
        let mut buf: Vec<u8> = Vec::new();
        self.iter_by_col_eq(
            ST_CONNECTION_CREDENTIALS_ID,
            StConnectionCredentialsFields::ConnectionId,
            &ConnectionIdViaU128::from(connection_id).into(),
        )?
            .next()
            .map(|row| row.read_via_bsatn::<StConnectionCredentialsRow>(&mut buf).map(|r| r.jwt_payload))
            .transpose()
            .map_err(|e| {
                log::error!(
                    "[{connection_id}]: get_jwt_payload: failed to get JWT payload for connection id ({connection_id}), error: {e}"
                );
                DatastoreError::Other(
                    anyhow!(
                        "Failed to get JWT payload for connection id ({connection_id}): {e}"
                    )
                )
            })
    }
}

/// Returns an iterator over all `st_column` rows for `table_id`.
pub(crate) fn iter_st_column_for_table<'a>(
    this: &'a (impl StateView + ?Sized),
    table_id: &'a AlgebraicValue,
) -> Result<impl 'a + Iterator<Item = RowRef<'a>>> {
    this.iter_by_col_eq(ST_COLUMN_ID, StColumnFields::TableId, table_id)
}

pub struct IterMutTx<'a> {
    tx_state_ins: Option<(&'a Table, &'a HashMapBlobStore)>,
    stage: ScanStage<'a>,

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Run the upgrade/migration path for the new version before serving connections
  2. Re-authenticate connections so stale credential rows are rewritten in the current format
  3. Verify the code path against a fresh database, then diff behavior against the upgraded one
  4. Report the decode failure with the versions involved
Defensive patterns

Strategy: try-catch

Try / catch

Wrap get_jwt_payload calls; on this error log the connection_id (as the datastore already does), fail authentication for that connection with a server-error (not a rejected-credential) status, and alert operators — the credential store needs migration or repair. Ok(None) is the normal no-credentials path and must not be conflated with this error.

Prevention

When it happens

Trigger: Authentication code calling get_jwt_payload on a database whose st_connection_credentials rows were serialized by an incompatible spacetimedb version; corrupted pages holding the row; a system-table schema change shipped without a data migration.

Common situations: Upgrading spacetimedb across versions that changed system-table layouts while keeping the data directory; long-lived databases reopened after major upgrades; mixed-version replicas.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/e5ec92dccdb55869. Report an issue: GitHub.