MuntashirAkon/AppManager · error · IOException
Invalid message length:
Error message
Invalid message length:
What it means
readMessage() reads a 4-byte length prefix and validates it before allocating; a negative length or one exceeding MAX_MESSAGE_SIZE indicates a corrupted or desynchronized frame, so it throws IOException("Invalid message length: " + len). This prevents huge or nonsensical allocations from untrusted input.
Solutions
- Verify both ends use the same DataTransmission framing/protocol version
- Ensure every sendMessage is flushed and lengths written on frame boundaries; resync or restart the connection on error
- Validate/sanitize any untrusted input before sending to keep frames well-formed
- Catch the IOException and re-establish the session (re-run shakeHands)
Example fix
// before
byte[] msg = transmission.sendAndReceiveMessage(request);
// after
byte[] msg;
try {
msg = transmission.sendAndReceiveMessage(request);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid message length")) {
transmission = recreateAndHandshake();
msg = transmission.sendAndReceiveMessage(request);
} else throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
byte[] msg = transmission.sendAndReceiveMessage(request);
} catch (IOException e) {
// Invalid message length: connection is desynchronized; re-establish session
transmission = recreateAndHandshake();
} Prevention
- Keep client and server protocol versions in sync
- Always write and flush complete frames
- Re-handshake on any framing error rather than continuing to read
- Never feed untrusted, unvalidated input through the channel
When it happens
Trigger: The peer sends malformed frames: stream desynchronization (offset misalignment after a failed write), a corrupted length header, a hostile client/server sending garbage, or reading with a stale/different framing version.
Common situations: Protocol version mismatch between client and server; data written without flush causing byte misalignment; MITM or injected garbage on the socket; reading after the peer died mid-frame.
Related errors
- Message is too large:
- Can't unparcel type " + actual.getName() + " in list of…
- Client protocol version:
- ERROR_MSG (constant; invalid/unknown file handle for…
- Invalid userId
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/4540d76c2e21f162.
Report an issue: GitHub.
Appendix: source
Thrown at libserver/src/main/java/io/github/muntashirakon/AppManager/server/common/DataTransmission.java:137
throw new IOException("Message is too large: " + messageBytes.length);
}
mOutputStream.writeInt(messageBytes.length);
mOutputStream.write(messageBytes);
mOutputStream.flush();
}
}
/**
* Read response as bytes after sending a message
*
* @return The bytes to be read
* @throws IOException When it fails to read the message
*/
@NonNull
private byte[] readMessage() throws IOException {
int len = mInputStream.readInt();
if (len < 0 || len > MAX_MESSAGE_SIZE) {
throw new IOException("Invalid message length: " + len);
}
byte[] bytes = new byte[len];
mInputStream.readFully(bytes, 0, len);
return bytes;
}
/**
* Send and receive messages at the same time (half-duplex)
*
* @param messageBytes Bytes to be sent
* @return Bytes to be read
* @throws IOException When it fails to send or read the message
* @see #sendMessage(String)
* @see #sendMessage(byte[])
*/
@NonNull
public synchronized byte[] sendAndReceiveMessage(@NonNull byte[] messageBytes) throws IOException {
sendMessage(messageBytes);View on GitHub (pinned to 0152f468fc)