redis/jedis · error · MalformedMaintenanceEventException

Malformed FAILING_OVER push

Error message

Malformed FAILING_OVER push: <content>

What it means

MaintenancePushCodec.failingOver() validates FAILING_OVER pushes, expecting [FAILING_OVER, Long seq, Long time_s, byte[] shards]. Deviations throw a malformed exception carrying the raw payload content, signaling the server sent a shape the client cannot decode.

Solutions

  1. Match jedis version to your Redis Enterprise server version (upgrade the client).
  2. Inspect the printed payload content to identify the schema drift and report it.
  3. Bypass proxies that might reshape RESP push arrays.
  4. After failover completes, verify the connection resubscribes and pushes parse normally.
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidFailingOver(List<Object> c) {
  return c.size() >= 4 && c.get(1) instanceof Long && c.get(2) instanceof Long
      && c.get(3) instanceof byte[];
}

Try / catch

try {
  handle(codec.decode(push));
} catch (JedisException e) {
  log.warn("Dropping malformed FAILING_OVER push: {}", e.getMessage());
}

Prevention

When it happens

Trigger: A FAILING_OVER push with <4 elements, non-Long seq/time_s, or non-byte[] shards arrives during a Redis Enterprise failover event.

Common situations: Failover events on clusters running different server/client schema versions; corrupted push streams; custom intermediaries; during rolling upgrades of the cluster.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/1e0b6cd629626dfa. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/MaintenancePushCodec.java:90

    // Explicit RESP3 null target => 'none' endpoint type (no remap). A byte[] target is parsed;
    // anything else (wrong type, unparseable) is malformed.
    HostAndPort target = c.get(3) == null ? null : parseHostPort(c, 3);
    return new MovingEvent((Long) c.get(1), (Long) c.get(2), target);
  }

  private static MaintenanceEvent migrating(List<Object> c) { // [MIGRATING, seq, time_s, shards]
    if (c.size() < 4 || !(c.get(1) instanceof Long) || !(c.get(2) instanceof Long)
        || !(c.get(3) instanceof byte[])) {
      throw malformed("MIGRATING", c);
    }
    return new MigratingEvent((Long) c.get(1), (Long) c.get(2), shardIds(c, 3));
  }

  private static MaintenanceEvent failingOver(List<Object> c) { // [FAILING_OVER, seq, time_s,
                                                                // shards]
    if (c.size() < 4 || !(c.get(1) instanceof Long) || !(c.get(2) instanceof Long)
        || !(c.get(3) instanceof byte[])) {
      throw malformed("FAILING_OVER", c);
    }
    return new FailingOverEvent((Long) c.get(1), (Long) c.get(2), shardIds(c, 3));
  }

  private static MaintenanceEvent migrated(List<Object> c) { // [MIGRATED, seq, shards]
    if (c.size() < 3 || !(c.get(1) instanceof Long) || !(c.get(2) instanceof byte[])) {
      throw malformed("MIGRATED", c);
    }
    return new MigratedEvent((Long) c.get(1), shardIds(c, 2));
  }

  private static MaintenanceEvent failedOver(List<Object> c) { // [FAILED_OVER, seq, shards]
    if (c.size() < 3 || !(c.get(1) instanceof Long) || !(c.get(2) instanceof byte[])) {
      throw malformed("FAILED_OVER", c);
    }
    return new FailedOverEvent((Long) c.get(1), shardIds(c, 2));
  }

View on GitHub (pinned to 6dac31d4c2)