{"record":{"id":"12ef40e40b9e34d5","repo":"apache/pulsar","slug":"package-metadata-is-in-legacy-java-serialization-f","errorCode":null,"errorMessage":"Package metadata is in legacy Java serialization format but reading it is disabled. Enable packagesManagementAllowLegacyJavaSerialization or re-upload the package.","messagePattern":"Package metadata is in legacy Java serialization format but reading it is disabled\\. Enable packagesManagementAllowLegacyJavaSerialization or re-upload the package\\.","errorType":"exception","errorClass":"MetadataFormatException","httpStatus":null,"severity":"error","filePath":"pulsar-package-management/core/src/main/java/org/apache/pulsar/packages/management/core/common/PackageMetadataUtil.java","lineNumber":85,"sourceCode":"            } catch (IOException e) {\n                throw new IllegalStateException(\"Failed to serialize package metadata as JSON\", e);\n            }\n        }\n        return SerializationUtils.serialize(packageMetadata);\n    }\n\n    public static PackageMetadata fromBytes(byte[] bytes, boolean allowLegacyJavaSerialization)\n            throws MetadataFormatException {\n        if (bytes == null || bytes.length == 0) {\n            throw new MetadataFormatException(\"Empty package metadata\");\n        }\n        int firstNonWhitespace = indexOfFirstNonWhitespace(bytes);\n        if (firstNonWhitespace >= 0 && bytes[firstNonWhitespace] == JSON_LEADING_BYTE) {\n            return readJson(bytes);\n        }\n        if (bytes.length >= 2 && bytes[0] == JAVA_MAGIC_BYTE_0 && bytes[1] == JAVA_MAGIC_BYTE_1) {\n            if (!allowLegacyJavaSerialization) {\n                throw new MetadataFormatException(\n                        \"Package metadata is in legacy Java serialization format but reading it is disabled. \"\n                                + \"Enable packagesManagementAllowLegacyJavaSerialization or re-upload the package.\");\n            }\n            return readLegacy(bytes);\n        }\n        throw new MetadataFormatException(\"Unrecognized package metadata format\");\n    }\n\n    private static PackageMetadata readJson(byte[] bytes) throws MetadataFormatException {\n        try {\n            return JSON_READER.readValue(bytes);\n        } catch (IOException e) {\n            throw new MetadataFormatException(\"Failed to parse package metadata as JSON: \" + e.getMessage());\n        }\n    }\n\n    private static PackageMetadata readLegacy(byte[] bytes) throws MetadataFormatException {\n        try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-package-management/core/src/main/java/org/apache/pulsar/packages/management/core/common/PackageMetadataUtil.java#L67-L103","documentation":"MetadataFormatException thrown by PackageMetadataUtil.fromBytes when the payload starts with the Java serialization magic bytes but the packagesManagementAllowLegacyJavaSerialization flag is disabled. Older Pulsar versions stored metadata via Java serialization; reading such blobs now requires explicitly opting in.","triggerScenarios":"Reading metadata of a package uploaded by an older Pulsar version (pre-JSON metadata) while the broker runs with packagesManagementAllowLegacyJavaSerialization=false (the safe default).","commonSituations":"Upgrading a cluster with packages uploaded by legacy versions, restoring old BookKeeper data into a new broker, or security-hardened deployments that keep legacy deserialization disabled.","solutions":["Re-upload the package with a current client so metadata is stored as JSON (recommended).","Temporarily set packagesManagementAllowLegacyJavaSerialization=true on the broker to read the legacy blob.","Confirm the blob's origin; if unexpected, treat it as possible tampering rather than enabling deserialization.","Migrate all legacy packages after upgrade, then keep the flag disabled permanently."],"exampleFix":"# before (broker.conf)\npackagesManagementAllowLegacyJavaSerialization=false\n# after (temporary migration only)\npackagesManagementAllowLegacyJavaSerialization=true","handlingStrategy":"fallback","validationCode":"static boolean isLegacyJavaSerialized(byte[] b) {\n    return b != null && b.length >= 2 && b[0] == (byte) 0xAC && b[1] == (byte) 0xED;\n}\n// if isLegacyJavaSerialized(blob) && !allowLegacy -> plan re-upload before upgrade","typeGuard":null,"tryCatchPattern":"try {\n    PackageMetadata m = PackageMetadataUtil.fromBytes(bytes, allowLegacy);\n} catch (MetadataFormatException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"legacy Java serialization\")) {\n        // surface actionable guidance: re-upload or enable the flag temporarily\n    }\n}","preventionTips":["Re-upload all packages after upgrading from legacy Pulsar versions.","Keep packagesManagementAllowLegacyJavaSerialization=false by default for security.","Inventory packages stored in legacy format before broker upgrades.","Alert on MetadataFormatException mentioning legacy format to catch old blobs early."],"tags":["deserialization","legacy","security","packages","upgrade"],"backgroundTag":"legacy-java-serialization-disabled","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}