apache/cassandra · error · MarshalException

Corrupt HintsDescriptor serialization, problem:

Error message

Corrupt HintsDescriptor serialization, problem: 

What it means

HintsDescriptor.decodeJSONBytes() throws MarshalException("Corrupt HintsDescriptor serialization, problem: ...") when the descriptor's parameters blob fails to parse as a JSON map (JsonUtils.fromJsonMap throws, e.g. on MarshalException from invalid types/values). This wraps the underlying parse failure so callers of HintsDescriptor.deserialize get a clear error instead of a null/NPE.

Source

Thrown at src/java/org/apache/cassandra/hints/HintsDescriptor.java:480

        validateCRC(in.readInt(), (int) crc.getValue());

        return new HintsDescriptor(hostId, version, timestamp, decodeJSONBytes(paramsBytes));
    }

    @SuppressWarnings("unchecked")
    private static ImmutableMap<String, Object> decodeJSONBytes(byte[] bytes)
    {
        // note: There is a Jackson module (datatype-guava) for directly reading into ImmutableMap,
        // but would require adding dependency to that
        try
        {
            return ImmutableMap.copyOf(JsonUtils.fromJsonMap(bytes));
        }
        catch (MarshalException e)
        {
            // Couple of options here: up to 4.0 simply returned null and caller failed with NPE.
            // Seems cleaner to throw an exception
            throw new MarshalException("Corrupt HintsDescriptor serialization, problem: " + e.getMessage(), e);
        }
    }

    private static void updateChecksumLong(CRC32 crc, long value)
    {
        updateChecksumInt(crc, (int) (value & 0xFFFFFFFFL));
        updateChecksumInt(crc, (int) (value >>> 32));
    }

    private static void validateCRC(int expected, int actual) throws IOException
    {
        if (expected != actual)
            throw new ChecksumMismatchException("Hints Descriptor CRC Mismatch");
    }
}

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove the corrupt hints file from the hints directory so the node skips it and continues.
  2. Check filesystem/disk health if multiple hints files show this error.
  3. Restore hints files from backup or accept data loss (hints are transient delivery aids; run repair to converge replicas).
  4. Upgrade/downgrade to matching Cassandra versions so descriptor parameter formats are compatible.

Example fix

// before
HintsDescriptor descriptor = HintsDescriptor.deserialize(input); // MarshalException
// after
try
{
    descriptor = HintsDescriptor.deserialize(input);
}
catch (IOException | MarshalException e)
{
    logger.warn("Discarding corrupt hints file", e);
    Files.deleteIfExists(hintsFilePath);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// quick sanity probe before full deserialize: file must start with a plausible descriptor
if (Files.size(hintsFile) < HintsDescriptor.ENCODED_SIZE) throw new IOException("hints file too small");

Try / catch

try { descriptor = HintsDescriptor.deserialize(input); } catch (IOException | MarshalException e) { logger.warn("Unreadable hints descriptor, removing file", e); Files.deleteIfExists(file); }

Prevention

When it happens

Trigger: Reading a hints file whose descriptor bytes were corrupted (truncated header, bit rot, torn write), or whose parameters JSON was written by an incompatible format/version. Reached via HintsDescriptor.deserialize while opening the hints file.

Common situations: Hints files damaged by hard reboot/power loss; hand-edited or copied hints files; version skew where a newer/older writer produced parameter JSON the reader rejects; disk corruption in the hints directory.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/03d3fe40f743b4bb. Report an issue: GitHub.