redis/jedis · warning
Ignoring malformed maintenance push
Error message
Ignoring malformed maintenance push: {} What it means
MaintenanceEventConsumer.handle receives a RESP push frame it recognizes as a maintenance event and decodes it with MaintenancePushCodec. If the payload is malformed (MalformedMaintenanceEventException), the consumer logs this warning with the raw content, calls context.drop() so the frame is still consumed (not surfaced as an unexpected push), and skips listener notification. The connection keeps working; only that maintenance event is lost.
Solutions
- Check the logged content to see what frame shape the server actually sent.
- Upgrade jedis to a version whose MaintenancePushCodec matches your Redis/managed-service push format.
- If behind a proxy (e.g. cluster proxy, load balancer with push injection), either bypass it for this client or disable maintenance-push handling in the client.
- Verify Redis server version compatibility with the client's maintenance events support.
- If frames are corrupted repeatedly, check for a protocol desync (shared connection misuse) — validate that no code writes raw commands on this connection.
Example fix
// before <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>6.0.0</version> <!-- codec older than server push format --> </dependency> // after <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>6.2.0</version> <!-- matches server's maintenance push format --> </dependency>
Defensive patterns
Strategy: try-catch
Validate before calling
// at registration time
if (!listeners.isEmpty() && !supportsMaintenancePushFormat(serverVersion)) {
log.warn("server push format may not match client codec; update jedis");
} Try / catch
try { event = MaintenancePushCodec.build(type, message); } catch (MalformedMaintenanceEventException e) { logger.warn("ignoring push: {}", content, e); context.drop(); } Prevention
- Keep jedis version aligned with your Redis/managed-service version's push format
- Bypass proxies that inject or rewrite RESP push frames for this client
- Register MaintenanceEventListeners you actually support; treat warnings as format drift signals
- Watch for repeated warnings from one connection — indicates protocol desync to investigate
When it happens
Trigger: Redis server (or an intermediary/proxy) emits a MOVING/MIGRATED/maintenance push whose payload doesn't match the expected codec format — e.g. unexpected field count, wrong types in the push message, or a proxy synthesizing its own push frames.
Common situations: Connecting through a proxy or managed Redis that alters or adds push messages the client codec doesn't understand; server version emitting a newer push format than this client version parses; corrupted/interleaved frames after a protocol desync.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed MOVING push:
- Unknown message type
- Unknown message type:
- Unexpected response
- Unexpected character!
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/8299f1f99e4e3776.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/MaintenanceEventConsumer.java:41
this.connection = connection;
this.listeners = listeners;
}
@Override
public PushConsumerContext handle(PushConsumerContext context) {
PushMessage message = context.getMessage();
MaintenancePushCodec.PushType type = MaintenancePushCodec.PushType.resolve(message.getType());
// not a maintenance event
if (type == null) {
return context;
}
MaintenanceEvent event;
try {
event = MaintenancePushCodec.build(type, message);
} catch (MalformedMaintenanceEventException e) {
logger.warn("Ignoring malformed maintenance push: {}", message.getContent(), e);
context.drop(); // recognized maintenance frame is consumed even when malformed
return context;
}
for (MaintenanceEventListener listener : listeners) {
event.accept(listener, connection);
}
context.drop();
return context;
}
}
View on GitHub (pinned to 6dac31d4c2)