Pumpkin-MC/Pumpkin · error · UpdateError

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

UpdateError::NotInitialized from pumpkin-plugin-utils' updater means an update check was requested before pumpkin_plugin_utils::init(context) ran, so the updater lacks the plugin context (id, version, marketplace client) needed to query the update endpoint. Like its license.rs counterpart, it signals a startup-order bug.

Solutions

  1. Call pumpkin_plugin_utils::init(context) before triggering any update check.
  2. Schedule update checks after the enabled/loaded hook, not in the constructor.
  3. Handle init's Result so a failed init is noticed before update checks run.
  4. If using a background task, spawn it after init completes and pass the initialized context.
  5. Unit-test startup order so the updater is never invoked pre-init.

Example fix

// before
fn on_load() {
    std::thread::spawn(|| check_for_update().ok()); // before init
}
// after
fn on_enable(ctx: &Context) -> Result<()> {
    pumpkin_plugin_utils::init(ctx)?;
    std::thread::spawn(|| check_for_update().ok());
    Ok(())
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard update checks behind an init flag
static INITED: AtomicBool = AtomicBool::new(false);
fn check_updates_safe() -> Option<UpdateInfo> {
    if !INITED.load(Ordering::Acquire) {
        tracing::warn!("skipping update check: plugin-utils not initialized");
        return None;
    }
    check_for_update().ok()
}

Type guard

fn is_not_initialized(e: &UpdateError) -> bool {
    matches!(e, UpdateError::NotInitialized)
}

Try / catch

match check_for_update() {
    Err(UpdateError::NotInitialized) => {
        tracing::error!("call pumpkin_plugin_utils::init(ctx) before update checks");
        None
    }
    other => other.ok(),
}

Prevention

When it happens

Trigger: Calling update-check functions (e.g. check_for_update) during plugin construction or before init(context) completed; init skipped; init called with a different context than the updater uses.

Common situations: Checking for updates in the plugin constructor; background update task spawned before initialization finished; init result ignored so the updater silently stayed uninitialized; reordered startup code after a refactor.

Related errors


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

Appendix: source

Thrown at crates/pumpkin-plugin-utils/src/updater.rs:14

//! Non-blocking update checks against the marketplace `/api/v1/rest/check-update` endpoint.

use crate::{
    http::{HttpClient, HttpError},
    models::CheckUpdateResponse,
};
use thiserror::Error;
use tracing::debug;

/// Update checking errors.
#[derive(Debug, Error)]
pub enum UpdateError {
    /// Plugin has not been initialized.
    #[error(
        "Plugin-utils has not been initialized (call pumpkin_plugin_utils::init(context) first)"
    )]
    NotInitialized,
    /// HTTP error when querying update endpoint.
    #[error("Failed to query update API: {0}")]
    Http(#[from] HttpError),
    /// JSON parsing error from response.
    #[error("Failed to parse update response JSON: {0}")]
    Json(#[from] serde_json::Error),
}

/// Checks for plugin updates against the Pumpkin Marketplace API.
pub struct UpdateChecker {
    http_client: HttpClient,
}

impl Default for UpdateChecker {
    fn default() -> Self {

View on GitHub (pinned to 8d4639e25a)