tinyhumansai/openhuman · error
consume login token response missing jwt
Error message
consume login token response missing jwt
What it means
Thrown by consume_login_token after a successful SDK call when the response JSON has no non-empty "jwt" string field. The request itself completed (context "consume login token through TinyHumans SDK" would fire earlier on transport/route failure), so this is a response-shape mismatch: the backend answered 2xx with an envelope that lacks data.jwt. Typical causes are a backend/SDK version skew in the envelope, or an error body returned with a success status.
Source
Thrown at src/api/rest.rs:538
// (see backend `routes/auth.ts`). The legacy
// `telegram/login-tokens/{token}/consume` path-param route was removed, so
// the old call 404'd and Telegram/OAuth-token login could never complete
// (WIRING_GAPS_AUDIT C1/C2).
let response = self
.sdk
.auth()
.consume_login_token(&tinyhumans_sdk::api::types::LoginTokenRequest {
token: token.to_string(),
})
.await
.context("consume login token through TinyHumans SDK")?;
let jwt = response
.get("jwt")
.and_then(Value::as_str)
.unwrap_or_default()
.trim()
.to_string();
anyhow::ensure!(!jwt.is_empty(), "consume login token response missing jwt");
Ok(jwt)
}
/// Validates that the provided session token is still active and accepted.
pub async fn validate_session_token(&self, bearer_jwt: &str) -> Result<()> {
let _ = self.fetch_current_user(bearer_jwt).await?;
Ok(())
}
/// Creates a short-lived link token for connecting a specific communication channel.
pub async fn create_channel_link_token(
&self,
channel: &str,
bearer_jwt: &str,
) -> Result<Value> {
let channel = channel.trim().trim_matches('/');
anyhow::ensure!(!channel.is_empty(), "channel is required");
let encoded_channel = urlencoding::encode(channel);View on GitHub (pinned to a221052e0d)
Solutions
- Verify the backend actually serves POST /auth/login-token/consume with the {token} body and returns {success, data:{jwt}} — the legacy path-param route was removed and old callers 404
- Log the full (redacted) response body to see which envelope arrived
- If the token may be stale or already consumed, restart the login flow to mint a fresh token instead of retrying consume
- Align core and SDK versions so the envelope contract matches
Example fix
// before
let jwt = client.consume_login_token(&token).await?;
// after
let jwt = match client.consume_login_token(&token).await {
Ok(jwt) => jwt,
Err(err) if err.to_string().contains("missing jwt") => {
anyhow::bail!("login token unusable (consumed or backend mismatch); restart login flow");
}
Err(err) => return Err(err),
}; Defensive patterns
Strategy: try-catch
Try / catch
let jwt = match client.consume_login_token(&token).await {
Ok(jwt) => jwt,
Err(err) if err.to_string().contains("missing jwt") => {
// 2xx but no data.jwt: stale/consumed token or backend envelope skew.
// Restart the login flow instead of retrying consume.
return Err(err.context("login token unusable; restart login flow"));
}
Err(err) => return Err(err),
}; Prevention
- Pin core, SDK, and backend versions together so the {success, data:{jwt}} envelope contract holds
- Log the redacted response body when consume fails to distinguish envelope skew from transport failure
- Never reuse a one-time login token; request a fresh link on any consume failure
When it happens
Trigger: POST /auth/login-token/consume returns {"success":true,"data":{}} or an error envelope without jwt — after a backend deploy changed the response shape, or when the token was already consumed and the backend signals that in-band.
Common situations: Backend and core versions out of sync (the route moved from the legacy telegram path-param form to the JSON body form), a stale login token being reused, or a proxy/inspection layer rewriting the body.
Related errors
- Model test RPC returned no result for ${workload} via ${prov
- API base URL must be an absolute http(s) URL with host
- login token is required
- {} {} failed ({status}): {text}
- OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/2149292042e4fbe9.
Report an issue: GitHub.