{"record":{"id":"83daf615a15ad759","repo":"Pumpkin-MC/Pumpkin","slug":"license-has-expired-on-0","errorCode":null,"errorMessage":"License has expired on {0}","messagePattern":"License has expired on (.+?)","errorType":"exception","errorClass":"LicenseError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin-plugin-utils/src/license.rs","lineNumber":27,"sourceCode":"    time::{Duration, SystemTime, UNIX_EPOCH},\n};\nuse thiserror::Error;\nuse tracing::{debug, info};\n\n/// License checking and verification errors.\n#[derive(Debug, Error)]\npub enum LicenseError {\n    /// HTTP communication error with marketplace.\n    #[error(\"Marketplace HTTP error: {0}\")]\n    Http(#[from] HttpError),\n    /// Metadata validation error (e.g. missing license on paid plugin).\n    #[error(\"License metadata mismatch: {0}\")]\n    MetadataMismatch(String),\n    /// License revoked or refunded by marketplace.\n    #[error(\"License was revoked or refunded: {0}\")]\n    Revoked(String),\n    /// License is expired.\n    #[error(\"License has expired on {0}\")]\n    Expired(String),\n    /// I/O error reading/writing license cache.\n    #[error(\"I/O error with license storage: {0}\")]\n    Io(#[from] std::io::Error),\n    /// JSON serialization error.\n    #[error(\"JSON serialization error: {0}\")]\n    Json(#[from] serde_json::Error),\n    /// Plugin is unsigned or missing marketplace metadata.\n    #[error(\"Plugin is unsigned or missing marketplace metadata\")]\n    UnsignedPlugin,\n    /// Plugin has not been initialized.\n    #[error(\n        \"Plugin-utils has not been initialized (call pumpkin_plugin_utils::init(context) first)\"\n    )]\n    NotInitialized,\n}\n\n/// Manages license checks, cached leases, and offline grace periods.","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-plugin-utils/src/license.rs#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet license = manager.verify()?; // Expired\n// after\nmatch manager.verify() {\n    Err(LicenseError::Expired(date)) => {\n        tracing::error!(\"license expired on {date}; renew at marketplace\");\n        prompt_renewal(date);\n    }\n    r => r?,\n}","handlingStrategy":"validation","validationCode":"// Check expiry locally from the cached lease before the license check fails\nif let Ok(lease) = load_cached_lease() {\n    if lease.expires_at <= chrono::Utc::now() {\n        tracing::warn!(\"license already expired at {} — renew first\", lease.expires_at);\n    }\n}","typeGuard":"fn is_expired(e: &LicenseError) -> bool {\n    matches!(e, LicenseError::Expired(_))\n}","tryCatchPattern":"match manager.verify() {\n    Err(LicenseError::Expired(date)) => {\n        tracing::error!(\"license expired {date}; renewing required\");\n        notify_admin_renewal(date);\n    }\n    other => other.map(|_| ()),\n}","preventionTips":["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."],"tags":["license","expiry","marketplace"],"backgroundTag":"license-expired","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}