redis/jedis · error · MalformedMaintenanceEventException

MOVING target must be a host:port byte[] at index

Error message

MOVING target must be a host:port byte[] at index 

What it means

When decoding a MOVING maintenance push event, Jedis expects the target field at the given index to be a byte[] containing "host:port". If the element is missing (index beyond the payload) or is not a byte array, the codec throws MalformedMaintenanceEventException with this message.

Solutions

  1. Verify the Redis server/proxy emits MOVING push events in the expected RESP array format with a byte[] host:port target
  2. Capture and inspect the raw push payload (the message is appended in the exception) to identify the structural mismatch
  3. Upgrade jedis and/or the server so both sides agree on the MOVING event schema
Defensive patterns

Strategy: try-catch

Try / catch

try {
  codec.decodeEvent(payload);
} catch (MalformedMaintenanceEventException e) {
  logger.warn("Dropping malformed MOVING push: {}", e.getMessage());
  // optionally reconnect to resynchronize push stream
}

Prevention

When it happens

Trigger: A CLIENT push message of type MOVING whose reply structure deviates from the expected layout — e.g. the target element absent, replaced by a string/long, or the message truncated by a proxy or incompatible server version.

Common situations: Connecting through a proxy or load balancer that rewrites or truncates push payloads; a server emitting a MOVING event in a different format than the client expects; fuzzed/corrupted push frames.

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/49187dde2a759fae. Report an issue: GitHub.

Appendix: source

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

    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));
  }

  /** Diagnostic shard-id list (stringified JSON array), logging only; required on the wire. */
  private static String shardIds(List<Object> c, int i) {
    return SafeEncoder.encode((byte[]) c.get(i));
  }

  /** MOVING target {@code host:port}; throws when the target is absent or unparseable. */
  private static HostAndPort parseHostPort(List<Object> c, int i) {
    if (i >= c.size() || !(c.get(i) instanceof byte[])) {
      throw new MalformedMaintenanceEventException(
          "MOVING target must be a host:port byte[] at index " + i + ": " + c);
    }
    try {
      return HostAndPort.from(SafeEncoder.encode((byte[]) c.get(i)));
    } catch (Exception e) {
      throw new MalformedMaintenanceEventException("Unparseable MOVING target: " + c, e);
    }
  }

  private static MalformedMaintenanceEventException malformed(String type, List<Object> c) {
    return new MalformedMaintenanceEventException("Malformed " + type + " push: " + c);
  }

  private MaintenancePushCodec() {
  }
}

View on GitHub (pinned to 6dac31d4c2)