Pumpkin-MC/Pumpkin · error · LicenseError
License has expired on
Error message
License has expired on {0} What it means
LicenseError::Expired means the plugin's license has passed its expiry date; the date is included via {0}. The marketplace or local lease validation determined the license term ended, so continued use is not permitted.
Solutions
- Renew the license/subscription on the marketplace.
- Verify server system clock/NTP is correct (wrong clock is a common false expiry).
- Re-run verification after renewal to refresh the cached lease.
- If the marketplace shows an active license, re-sync/re-verify to update local cache.
- Contact marketplace support if expiry date ({0}) contradicts your account.
Example fix
// before
let license = manager.verify()?; // Expired
// after
match manager.verify() {
Err(LicenseError::Expired(date)) => {
tracing::error!("license expired on {date}; renew at marketplace");
prompt_renewal(date);
}
r => r?,
} Defensive patterns
Strategy: validation
Validate before calling
// Check expiry locally from the cached lease before the license check fails
if let Ok(lease) = load_cached_lease() {
if lease.expires_at <= chrono::Utc::now() {
tracing::warn!("license already expired at {} — renew first", lease.expires_at);
}
} Type guard
fn is_expired(e: &LicenseError) -> bool {
matches!(e, LicenseError::Expired(_))
} Try / catch
match manager.verify() {
Err(LicenseError::Expired(date)) => {
tracing::error!("license expired {date}; renewing required");
notify_admin_renewal(date);
}
other => other.map(|_| ()),
} Prevention
- Sync server clock via NTP to avoid false expiry.
- Track license renewal dates and renew before expiry.
- Refresh the cached lease while online so grace periods stay accurate.
- Set up alerts for upcoming expirations.
When it happens
Trigger: License verification finds the license's expiry timestamp in the past — either reported by the marketplace API or computed from the cached lease after the offline grace period plus expiry have both lapsed.
Common situations: Annual/subscription license ran out; trial license ended; server clock set far in the future (system time skew) making a valid license look expired; renewal payment failed silently.
Related errors
- License was revoked or refunded
- Marketplace HTTP error
- License metadata mismatch
- Plugin is unsigned or missing marketplace metadata
- Plugin-utils has not been initialized (call…
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/83daf615a15ad759.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin-plugin-utils/src/license.rs:27
time::{Duration, SystemTime, UNIX_EPOCH},
};
use thiserror::Error;
use tracing::{debug, info};
/// License checking and verification errors.
#[derive(Debug, Error)]
pub enum LicenseError {
/// HTTP communication error with marketplace.
#[error("Marketplace HTTP error: {0}")]
Http(#[from] HttpError),
/// Metadata validation error (e.g. missing license on paid plugin).
#[error("License metadata mismatch: {0}")]
MetadataMismatch(String),
/// License revoked or refunded by marketplace.
#[error("License was revoked or refunded: {0}")]
Revoked(String),
/// License is expired.
#[error("License has expired on {0}")]
Expired(String),
/// I/O error reading/writing license cache.
#[error("I/O error with license storage: {0}")]
Io(#[from] std::io::Error),
/// JSON serialization error.
#[error("JSON serialization error: {0}")]
Json(#[from] serde_json::Error),
/// Plugin is unsigned or missing marketplace metadata.
#[error("Plugin is unsigned or missing marketplace metadata")]
UnsignedPlugin,
/// Plugin has not been initialized.
#[error(
"Plugin-utils has not been initialized (call pumpkin_plugin_utils::init(context) first)"
)]
NotInitialized,
}
/// Manages license checks, cached leases, and offline grace periods.View on GitHub (pinned to 8d4639e25a)