apache/pulsar · error · MetadataFormatException

Package metadata is in legacy Java serialization format but

Error message

Package metadata is in legacy Java serialization format but reading it is disabled. Enable packagesManagementAllowLegacyJavaSerialization or re-upload the package.

What it means

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.

Source

Thrown at pulsar-package-management/core/src/main/java/org/apache/pulsar/packages/management/core/common/PackageMetadataUtil.java:85

            } catch (IOException e) {
                throw new IllegalStateException("Failed to serialize package metadata as JSON", e);
            }
        }
        return SerializationUtils.serialize(packageMetadata);
    }

    public static PackageMetadata fromBytes(byte[] bytes, boolean allowLegacyJavaSerialization)
            throws MetadataFormatException {
        if (bytes == null || bytes.length == 0) {
            throw new MetadataFormatException("Empty package metadata");
        }
        int firstNonWhitespace = indexOfFirstNonWhitespace(bytes);
        if (firstNonWhitespace >= 0 && bytes[firstNonWhitespace] == JSON_LEADING_BYTE) {
            return readJson(bytes);
        }
        if (bytes.length >= 2 && bytes[0] == JAVA_MAGIC_BYTE_0 && bytes[1] == JAVA_MAGIC_BYTE_1) {
            if (!allowLegacyJavaSerialization) {
                throw new MetadataFormatException(
                        "Package metadata is in legacy Java serialization format but reading it is disabled. "
                                + "Enable packagesManagementAllowLegacyJavaSerialization or re-upload the package.");
            }
            return readLegacy(bytes);
        }
        throw new MetadataFormatException("Unrecognized package metadata format");
    }

    private static PackageMetadata readJson(byte[] bytes) throws MetadataFormatException {
        try {
            return JSON_READER.readValue(bytes);
        } catch (IOException e) {
            throw new MetadataFormatException("Failed to parse package metadata as JSON: " + e.getMessage());
        }
    }

    private static PackageMetadata readLegacy(byte[] bytes) throws MetadataFormatException {
        try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Re-upload the package with a current client so metadata is stored as JSON (recommended).
  2. Temporarily set packagesManagementAllowLegacyJavaSerialization=true on the broker to read the legacy blob.
  3. Confirm the blob's origin; if unexpected, treat it as possible tampering rather than enabling deserialization.
  4. Migrate all legacy packages after upgrade, then keep the flag disabled permanently.

Example fix

# before (broker.conf)
packagesManagementAllowLegacyJavaSerialization=false
# after (temporary migration only)
packagesManagementAllowLegacyJavaSerialization=true
Defensive patterns

Strategy: fallback

Validate before calling

static boolean isLegacyJavaSerialized(byte[] b) {
    return b != null && b.length >= 2 && b[0] == (byte) 0xAC && b[1] == (byte) 0xED;
}
// if isLegacyJavaSerialized(blob) && !allowLegacy -> plan re-upload before upgrade

Try / catch

try {
    PackageMetadata m = PackageMetadataUtil.fromBytes(bytes, allowLegacy);
} catch (MetadataFormatException e) {
    if (e.getMessage() != null && e.getMessage().contains("legacy Java serialization")) {
        // surface actionable guidance: re-upload or enable the flag temporarily
    }
}

Prevention

When it happens

Trigger: Reading metadata of a package uploaded by an older Pulsar version (pre-JSON metadata) while the broker runs with packagesManagementAllowLegacyJavaSerialization=false (the safe default).

Common situations: 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.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/12ef40e40b9e34d5. Report an issue: GitHub.