Pumpkin-MC/Pumpkin · error · LicenseError
I/O error with license storage
Error message
I/O error with license storage: {0} What it means
LicenseError::Io wraps std::io::Error (#[from]) from reading or writing the license cache on disk. The library persists license leases for offline grace; a filesystem failure while loading or saving that cache is surfaced here. The underlying OS error is embedded via {0}.
Solutions
- Check the license cache path exists and is writable by the server process (permissions/ownership).
- Ensure the parent directory exists (the library may not create it) or create it manually.
- Free disk space / raise quota if the write failed due to space.
- Run the server as a user with access to the data directory; fix read-only mounts.
- Inspect {0} for the specific OS error (Permission denied, No space left, Is a directory).
Example fix
// before
std::fs::create_dir_all("plugins/.licenses"); // was missing
drop(manager.verify());
// after
let cache_dir = Path::new("plugins/.licenses");
std::fs::create_dir_all(&cache_dir)?;
// verify cache is writable
let probe = cache_dir.join(".probe");
std::fs::write(&probe, b"")?;
std::fs::remove_file(&probe)?; Defensive patterns
Strategy: try-catch
Validate before calling
// Verify cache directory is writable before license operations
let dir = Path::new("plugins/.licenses");
std::fs::create_dir_all(dir)?;
let probe = dir.join(".write_probe");
std::fs::write(&probe, b"")?;
std::fs::remove_file(&probe)?; Type guard
fn is_io_error(e: &LicenseError) -> bool {
matches!(e, LicenseError::Io(_))
} Try / catch
match manager.verify() {
Err(LicenseError::Io(e)) => {
tracing::warn!("license cache I/O failed: {e}; running without cache");
verify_without_cache()
}
other => other.map(|_| ()),
} Prevention
- Provision a writable data directory for the server process.
- Run the server under a user with ownership of the data dir.
- Monitor disk space/quota on the host.
- Never mount the data directory read-only.
When it happens
Trigger: Loading the cached lease at startup or writing a refreshed lease after verification when file open/read/write fails: missing parent directory, insufficient permissions, disk full, or the cache path points to something unusable (e.g. a directory).
Common situations: Read-only filesystem or container with no writable data dir; cache directory deleted between runs; running the server under a user lacking permissions on the cache path; disk quota/full disk; cache file corrupted at the OS level.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/24540f3600afc8f6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin-plugin-utils/src/license.rs:30
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.
pub struct LicenseChecker {
data_folder: PathBuf,
http_client: HttpClient,View on GitHub (pinned to 8d4639e25a)