Pumpkin-MC/Pumpkin · error · LicenseError
Plugin-utils has not been initialized (call…
Error message
Plugin-utils has not been initialized (call pumpkin_plugin_utils::init(context) first)
What it means
LicenseError::NotInitialized means the plugin called a license API before pumpkin_plugin_utils::init(context) ran, so the LicenseManager has no plugin context to operate with. It is a pure ordering bug in the plugin's startup sequence, not an environmental failure.
Solutions
- Call pumpkin_plugin_utils::init(context) before any license API usage, ideally first in the plugin's load/enable hook.
- Move license verification out of the constructor into a post-init lifecycle callback.
- Ensure init's Result is checked — a failed init leaves the manager unusable.
- Verify the same context/plugin instance used for init is the one performing checks.
- If init runs in async setup, await/complete it before license calls.
Example fix
// before
impl Plugin for MyPlugin {
fn new() -> Self { Self { license: verify_license() } } // too early
}
// after
impl Plugin for MyPlugin {
fn on_enable(&mut self, ctx: &Context) -> Result<()> {
pumpkin_plugin_utils::init(ctx)?;
self.license = verify_license()?;
Ok(())
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Guard: only call license APIs after explicit init
static INITED: AtomicBool = AtomicBool::new(false);
fn ensure_inited() -> Result<(), LicenseError> {
if INITED.load(Ordering::Acquire) { Ok(()) }
else { Err(LicenseError::NotInitialized) }
} Type guard
fn is_not_initialized(e: &LicenseError) -> bool {
matches!(e, LicenseError::NotInitialized)
} Try / catch
match manager.verify() {
Err(LicenseError::NotInitialized) => {
tracing::error!("init before license check: pumpkin_plugin_utils::init(ctx)");
return Err(anyhow!("plugin-utils not initialized"));
}
other => other.map(|_| ()),
} Prevention
- Call pumpkin_plugin_utils::init(context) as the first line of the enable hook.
- Never run license checks in the plugin constructor.
- Always unwrap/propagate init's Result.
- Add a startup-order integration test.
When it happens
Trigger: Calling LicenseManager methods (verify, cached lease access, etc.) on the plugin's construction or before the init(context) call completes; init skipped entirely; init called on a different plugin instance/context than the one being checked.
Common situations: Performing license checks in the plugin constructor instead of the enabled/loaded lifecycle hook; refactoring moved license code earlier in startup; multiple plugins sharing a static manager initialized by only one of them; early-return/panic in init leaving it uninitialized.
Related errors
- Plugin-utils has not been initialized (call…
- Plugin initialization failed
- Marketplace HTTP error
- License metadata mismatch
- Failed to load library
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/55dc4948a0c79aaa.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin-plugin-utils/src/license.rs:39
#[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 {
/// Creates a new `LicenseChecker` instance for the given data folder.
#[must_use]
pub fn new(data_folder: impl AsRef<Path>) -> Self {
let folder = data_folder.as_ref().to_path_buf();
Self {
data_folder: folder,View on GitHub (pinned to 8d4639e25a)