Pumpkin-MC/Pumpkin · error · LoginError
Cannot accept self-signed token. Authentication is enforced…
Error message
Cannot accept self-signed token. Authentication is enforced by server config.
What it means
This is the LoginError::SelfSignedNotAllowed variant. Bedrock clients may present a self-signed JWT chain (used for local/LAN play without Xbox Live). When the server is configured to enforce Xbox Live authentication, Pumpkin refuses these self-signed tokens outright. The library throws it to enforce the server's online-auth policy.
Solutions
- Have the player sign into Xbox Live in their Bedrock client and reconnect
- If offline/self-signed logins are acceptable for this server, disable enforced authentication in the server config and restart
- If this is a test harness, generate a token through the real Xbox Live flow instead of self-signing
- Communicate the requirement to the player: self-signed tokens can never bypass an auth-enforced server
Example fix
// before (pumpkin.toml) [authentication] enforce = true # offline clients rejected // after (only if self-signed play is acceptable) [authentication] enforce = false # allows self-signed/local tokens
Defensive patterns
Strategy: try-catch
Validate before calling
// Before connecting, confirm the client holds a real Xbox Live token,
// not a self-signed chain, when the server enforces auth
fn can_attempt_login(has_xbox_token: bool, server_enforces_auth: bool) -> bool {
!server_enforces_auth || has_xbox_token
} Type guard
fn is_self_signed_rejected(e: &LoginError) -> bool {
matches!(e, LoginError::SelfSignedNotAllowed)
} Try / catch
match login_result {
Err(LoginError::SelfSignedNotAllowed) => {
disconnect_with("This server requires Xbox Live authentication. Sign in and retry.")
}
Err(e) => disconnect_with(&format!("Login failed: {e}")),
Ok(p) => admit(p),
} Prevention
- Sign into Xbox Live before joining auth-enforced servers
- Match the server's authentication config with your player base (offline vs online)
- Never attempt to bypass enforcement with self-signed certificates
- Document the auth requirement in your server's MOTD/rules
When it happens
Trigger: A client that is not signed into Xbox Live (or a tool that self-generates its key pair) sends a self-signed JWT chain in the Login packet while the server config has authentication enforcement enabled.
Common situations: LAN or offline players trying to join an auth-enforced server, testing tools using self-generated certificates, or server operators who enabled authentication but expect offline clients to connect.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- JWT chain validation failed
- The validated username is invalid
- Could not parse UUID from validated token
- Got a guest/splitscreen login request. Currently…
- Failed to verify Ed25519 signature
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/d36981bb4eee3571.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin/src/net/bedrock/login/mod.rs:40
use pumpkin_world::{CURRENT_BEDROCK_MC_PROTOCOL, CURRENT_BEDROCK_MC_VERSION};
use serde::{Deserialize, de::Error};
use serde_repr::Deserialize_repr;
use std::sync::Arc;
use thiserror::Error;
use tracing::debug;
use uuid::Uuid;
#[derive(Debug, Error)]
pub enum LoginError {
#[error("Login packet data is not valid JSON")]
InvalidTokenFormat(#[from] serde_json::Error),
#[error("JWT chain validation failed: {0}")]
ChainValidationFailed(#[from] AuthError),
#[error("The validated username is invalid")]
InvalidUsername,
#[error("Could not parse UUID from validated token")]
InvalidUuid,
#[error("Cannot accept self-signed token. Authentication is enforced by server config.")]
SelfSignedNotAllowed,
#[error("Got a guest/splitscreen login request. Currently unimplemented.")]
GuestUnimplemented,
#[error("Failed to decode extra using decode_b64_url_nopad.")]
DecodeExtraError,
}
#[derive(Deserialize_repr)]
#[repr(u8)]
enum AuthenticationType {
Full,
Guest,
SelfSigned,
}
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct AuthPayload {View on GitHub (pinned to 8d4639e25a)