Pumpkin-MC/Pumpkin · error · LicenseError

JSON serialization error

Error message

JSON serialization error: {0}

What it means

LicenseError::Json wraps serde_json::Error (#[from]) from serializing or deserializing license data — chiefly the cached lease file on disk, or parsing marketplace JSON payloads. A malformed or corrupted cache file is the most common source. The serde error detail is embedded via {0}.

Solutions

  1. Delete the license cache file and re-verify online to write a fresh lease.
  2. Match the plugin-utils version to the one that wrote the cache (schema drift after upgrades).
  3. If the error names a marketplace response, check for marketplace API changes and update plugin-utils.
  4. Restore the cache from backup or let the library regenerate it (requires connectivity).
  5. Inspect {0} — 'missing field'/'invalid type' point at schema mismatch; 'EOF while parsing' at truncation.

Example fix

// before
let lease: LicenseLease = serde_json::from_str(&cache)?; // schema drift
// after
let lease = match serde_json::from_str::<LicenseLease>(&cache) {
    Ok(l) => l,
    Err(e) => {
        tracing::warn!("license cache unusable ({e}); re-verifying online");
        std::fs::remove_file(&cache_path).ok();
        manager.verify_online()?
    }
};
Defensive patterns

Strategy: fallback

Validate before calling

// Sanity-check the cache file parses before handing it to the manager
if let Ok(raw) = std::fs::read_to_string(&cache_path) {
    if serde_json::from_str::<serde_json::Value>(&raw).is_err() {
        tracing::warn!("license cache corrupt; deleting before verify");
        let _ = std::fs::remove_file(&cache_path);
    }
}

Type guard

fn is_json_error(e: &LicenseError) -> bool {
    matches!(e, LicenseError::Json(_))
}

Try / catch

match manager.verify() {
    Err(LicenseError::Json(e)) => {
        tracing::warn!("cache schema mismatch ({e}); re-verifying online");
        let _ = std::fs::remove_file(&cache_path);
        manager.verify_online()
    }
    other => other,
}

Prevention

When it happens

Trigger: Deserializing the license cache file whose JSON no longer matches the current struct schema (library upgrade changed fields), or the file was truncated/hand-edited; also serializing the lease before writing, or decoding an unexpected marketplace API response body.

Common situations: Upgrading the plugin (or plugin-utils) after the lease struct changed, leaving an incompatible cache; partially written cache from a crash; manual edits to the cache file; marketplace API response shape changed.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/f979bd638e327825. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin-plugin-utils/src/license.rs:33

#[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.
pub struct LicenseChecker {
    data_folder: PathBuf,
    http_client: HttpClient,
}

impl LicenseChecker {

View on GitHub (pinned to 8d4639e25a)