{"record":{"id":"cb2ee584d3fd629b","repo":"Pumpkin-MC/Pumpkin","slug":"plugin-is-unsigned-or-missing-marketplace-metadata","errorCode":null,"errorMessage":"Plugin is unsigned or missing marketplace metadata","messagePattern":"Plugin is unsigned or missing marketplace metadata","errorType":"exception","errorClass":"LicenseError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin-plugin-utils/src/license.rs","lineNumber":36,"sourceCode":"    #[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.\npub struct LicenseChecker {\n    data_folder: PathBuf,\n    http_client: HttpClient,\n}\n\nimpl LicenseChecker {\n    /// Creates a new `LicenseChecker` instance for the given data folder.\n    #[must_use]\n    pub fn new(data_folder: impl AsRef<Path>) -> Self {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-plugin-utils/src/license.rs#L18-L54","documentation":"LicenseError::UnsignedPlugin is a fieldless variant indicating the plugin carries no signature or is missing marketplace metadata entirely, so license verification cannot even identify it. Unlike MetadataMismatch (metadata present but wrong), this fires when the required marketplace/signature data is absent.","triggerScenarios":"Running license checks on a plugin built locally or distributed outside the marketplace without embedded signing/marketplace metadata; metadata stripped by repackaging; loading a jar whose manifest lacks the expected marketplace entries.","commonSituations":"Developer testing an in-development build through the paid-plugin flow; third-party mirror site download with metadata stripped; unzip/rezip of the plugin losing manifest entries; mixing up a free unsigned plugin with a license-gated one.","solutions":["Install the plugin from the official marketplace so signed metadata is present.","Rebuild with the official publishing toolchain that embeds signing/marketplace metadata.","Do not repackage/rezip the plugin jar, which can drop metadata.","Verify the correct plugin file is license-gated; unsigned free plugins should skip license checks.","If you believe the plugin is signed, verify the jar's manifest contains the marketplace metadata keys."],"exampleFix":"// before (manual repackage)\nzip -r myplugin.jar extracted/           // metadata lost -> UnsignedPlugin\n// after\nmvn pumpkin:publish && install dist/myplugin-1.2.0.jar  // signed build","handlingStrategy":"validation","validationCode":"// Verify the packaged plugin carries marketplace metadata before enabling license flow\nlet jar = std::fs::File::open(\"plugins/myplugin.jar\")?;\nlet mut archive = zip::ZipArchive::new(jar)?;\nlet manifest = archive.by_name(\"META-INF/MANIFEST.MF\")?;\nlet text = std::io::read_to_string(manifest)?;\nif !text.contains(\"Marketplace-Id\") {\n    panic!(\"plugin jar lacks marketplace metadata — rebuild via official pipeline\");\n}","typeGuard":"fn is_unsigned(e: &LicenseError) -> bool {\n    matches!(e, LicenseError::UnsignedPlugin)\n}","tryCatchPattern":"match manager.verify() {\n    Err(LicenseError::UnsignedPlugin) => {\n        tracing::error!(\"plugin is unsigned; install official marketplace build\");\n        disable_paid_features();\n    }\n    other => other.map(|_| ()),\n}","preventionTips":["Install plugins only from the official marketplace.","Never rezip/repackage plugin jars.","Build with the official publishing toolchain that signs artifacts.","Skip license checks for genuinely free unsigned plugins."],"tags":["license","signing","metadata"],"backgroundTag":"missing-required-config-field","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"}