Bugs and issues discovered during AMQP interoperability testing that should be investigated and reported upstream. Each entry includes a minimal reproducer.
Language limitations (Java/C# 16-bit char, JavaScript Number precision) are excluded — those are inherent to the platform, not library bugs.
Library: Apache Qpid ProtonJ2 (Java) Severity: Crash (sender cannot send valid AMQP list) AMQP spec: A list MAY contain null elements. A list containing [string, null] is valid.
When a list body contains a null element after a non-null element, the ListTypeEncoder throws a NullPointerException because it tries to look up the encoder for the null element‘s type after having cached the previous element’s encoder.
// repro: ProtonJ2ListNullBug.java // compile: javac -cp protonj2-client-1.0.0-M22.jar ProtonJ2ListNullBug.java // run: java -cp .:protonj2-client-1.0.0-M22.jar ProtonJ2ListNullBug import org.apache.qpid.protonj2.client.*; import java.util.*; public class ProtonJ2ListNullBug { public static void main(String[] args) throws Exception { Client client = Client.create(); Connection conn = client.connect("localhost", 5672, new ConnectionOptions().user("artemis").password("artemis")); Sender sender = conn.openSender("test.list.null.bug"); List<Object> body = new ArrayList<>(); body.add("hello"); body.add(null); // null after non-null triggers NPE Message<List<Object>> msg = Message.create(body); sender.send(msg); // throws NullPointerException in ListTypeEncoder conn.close(); } }
Library: Apache Qpid Proton .NET Severity: Crash (sender cannot send valid AMQP list) AMQP spec: Same as above — null elements in lists are valid.
Same root cause as the ProtonJ2 bug: the .NET ListTypeEncoder crashes when encoding a null element that follows a non-null element.
// repro: ListNullBug.cs // run: dotnet run using Apache.Qpid.Proton.Client; var client = IClient.Create(); var options = new ConnectionOptions { User = "artemis", Password = "artemis" }; using var conn = client.Connect("localhost", 5672, options); using var sender = conn.OpenSender("test.list.null.bug"); var msg = IMessage<object>.Create(); msg.Body = new List<object> { "hello", null }; // null after non-null triggers NRE sender.Send(msg); // throws NullReferenceException in ListTypeEncoder
Library: Apache Qpid ProtonJ2 (Java) Severity: Data corruption (sends wrong codepoint) AMQP spec: The char type is a single Unicode character (any valid codepoint including U+0000).
When ProtonJ2 sends a char value of U+0000 (null character), the receiver gets a different codepoint. The encoding path appears to special-case or skip the zero value.
// repro: ProtonJ2CharBug.java import org.apache.qpid.protonj2.client.*; public class ProtonJ2CharBug { public static void main(String[] args) throws Exception { Client client = Client.create(); Connection conn = client.connect("localhost", 5672, new ConnectionOptions().user("artemis").password("artemis")); Sender sender = conn.openSender("test.char.null.bug"); // Send U+0000 as a char Message<Character> msg = Message.create('�'); sender.send(msg); // Receiver (any client) gets a different codepoint than U+0000 conn.close(); } }
Library: Apache Qpid ProtonJ2 (Java) Severity: Data corruption (value changes sign) AMQP spec: ulong is an unsigned 64-bit integer (0 to 2^64-1).
ProtonJ2 decodes AMQP ulong values greater than Long.MAX_VALUE (2^63-1) as negative Java long values, because Java has no unsigned 64-bit integer type and the library does not compensate.
// repro: ProtonJ2UlongBug.java // Send from Python: // python3 shim.py send --broker amqp://localhost:5672 --queue test.ulong.bug \ // --type ulong --count 1 --data '[{"index":0, "value":"18446744073709551615"}]' // Receive with Java ProtonJ2: // java ProtonJ2UlongBug // Expected: 18446744073709551615 (ULONG_MAX) // Actual: -1 (signed interpretation) import org.apache.qpid.protonj2.client.*; public class ProtonJ2UlongBug { public static void main(String[] args) throws Exception { Client client = Client.create(); Connection conn = client.connect("localhost", 5672, new ConnectionOptions().user("artemis").password("artemis")); Receiver receiver = conn.openReceiver("test.ulong.bug"); Delivery delivery = receiver.receive(10_000); Object body = delivery.message().body(); System.out.println("Received: " + body); // Prints -1 instead of 18446744073709551615 conn.close(); } }
Library: Apache Qpid ProtonJ2 (Java) Severity: Type loss (correct value, wrong Java type) AMQP spec: The timestamp type represents an absolute point in time (ms since Unix epoch).
When receiving an AMQP timestamp value, ProtonJ2 returns a java.lang.Long instead of a java.util.Date (or similar temporal type). The raw millisecond value is correct, but the type information is lost — the receiver cannot distinguish a timestamp from a plain long.
// Receive a message containing an AMQP timestamp: Delivery delivery = receiver.receive(10_000); Object body = delivery.message().body(); System.out.println(body.getClass().getName()); // Expected: java.util.Date (or similar) // Actual: java.lang.Long
Library: Apache Qpid ProtonJ2 (Java) Severity: Data corruption / type loss AMQP spec: Lists may contain elements of any AMQP type, including binary and timestamp.
When binary or timestamp values appear as elements within an AMQP list, ProtonJ2 decodes them incorrectly. Binary data may be returned as a String (UTF-8 interpretation), and timestamp may lose its temporal type.
// Send from Python: // List body = [b'\x00\x01\x02', timestamp(1234567890000)] // Receive with ProtonJ2: // List elements are decoded with wrong types
Library: Apache Qpid ProtonJ2 (Java) Severity: Missing feature (JMS spec compliance) JMS spec: JMSCorrelationID can be a byte array via setJMSCorrelationIDAsBytes().
ProtonJ2's message-id type restriction prevents setting a binary (byte[]) value as the correlation ID. The AMQP spec allows message-id (and by extension correlation-id) to be uuid, ulong, binary, or string.
Message<String> msg = Message.create("test"); msg.correlationId(new byte[] {0x01, 0x02, 0x03}); // Throws or silently fails — binary correlation ID not supported
Library: Apache Qpid Proton .NET Severity: Missing feature (same as ProtonJ2)
Neither byte[] nor IProtonBuffer is accepted by the .NET Proton encoder for the correlation-id field.
var msg = IMessage<object>.Create(); msg.Body = "test"; msg.CorrelationId = new byte[] { 0x01, 0x02, 0x03 }; // Encoder rejects binary — only string/ulong/uuid accepted
Library: Apache Qpid Proton .NET Severity: Type loss (correct value, wrong .NET type) AMQP spec: Same as bug #5 — timestamp is a distinct AMQP type.
When receiving an AMQP timestamp, Proton .NET returns System.Int64 (raw milliseconds) instead of System.DateTime or System.DateTimeOffset. The value is correct but the type is lost.
// Receive a message containing an AMQP timestamp: var delivery = receiver.Receive(TimeSpan.FromSeconds(10)); var body = delivery.Message().Body; Console.WriteLine(body.GetType().Name); // Expected: DateTime or DateTimeOffset // Actual: Int64
Library: Apache Qpid Proton .NET Severity: Data corruption (wrong AMQP type on wire) AMQP spec: binary is a distinct type from array-of-ubyte. They have different type codes.
When a byte[] appears as an element within a list, Proton .NET encodes it as an AMQP array<ubyte> instead of AMQP binary. This is because byte[] implements IList<byte>, and the encoder picks the array path. Other clients decode this as an array of integers rather than a binary blob.
var msg = IMessage<object>.Create(); msg.Body = new List<object> { new byte[] { 0x01, 0x02, 0x03 } // encoded as array<ubyte>, not binary }; sender.Send(msg); // Other clients receive [1, 2, 3] (array of ints) instead of b'\x01\x02\x03'
Library: Apache Qpid Proton .NET Severity: Type loss (wrong type on decode) AMQP spec: array-of-ubyte and binary are distinct types.
The inverse of bug #10: when receiving a valid AMQP array<ubyte>, Proton .NET decodes it as byte[] which is then indistinguishable from binary data.
Library: Apache Qpid Proton .NET Severity: Type loss AMQP spec: An empty binary value (zero-length) is valid and distinct from null.
When Proton .NET sends and receives an empty binary (new byte[0]), the round-tripped value comes back as a different type (null or empty string).
var msg = IMessage<object>.Create(); msg.Body = new byte[0]; // empty binary sender.Send(msg); // .NET receiver gets null or wrong type instead of empty byte[]
Library: Apache Qpid Proton .NET (sender) + ProtonJ2 (receiver) Severity: Interop failure (all binary values fail)
When Proton .NET sends binary data, ProtonJ2 cannot decode any of it correctly. This affects all binary test values, not just edge cases. The encoding produced by .NET may use a format or type descriptor that ProtonJ2's binary decoder does not expect.
# Reproduce:
# 1. Send with .NET: dotnet-shim send --type binary --data '[{"index":0,"value":"AQID"}]' ...
# 2. Receive with Java ProtonJ2: java-shim receive ...
# All binary values fail to decode correctly
Library: AMQP Rhea (JavaScript) Severity: Data corruption / crash Root cause: JavaScript Number is IEEE 754 double — safe integer range is -(2^53-1) to 2^53-1.
This is partly a language limitation, but the library should use BigInt for 64-bit integer types rather than silently losing precision or throwing RangeError.
For ulong values > 2^53 and long values with |v| > 2^53: the value is silently rounded to the nearest representable double. For some extreme values, a RangeError is thrown during encoding.
// repro: rhea_precision.js const rhea = require('rhea'); const container = rhea.create_container(); container.once('sendable', (context) => { // This value (ULONG_MAX) will be silently corrupted context.sender.send({ body: rhea.types.wrap_ulong(0xFFFFFFFFFFFFFFFFn) }); // JS Number cannot represent this — precision loss or RangeError });
| # | Library | Bug | Severity |
|---|---|---|---|
| 1 | ProtonJ2 | List NPE on null-after-non-null | Crash |
| 2 | Proton .NET | List NRE on null-after-non-null | Crash |
| 3 | ProtonJ2 | Char U+0000 encoding error | Data corruption |
| 4 | ProtonJ2 | ulong > 2^63 decoded as negative | Data corruption |
| 5 | ProtonJ2 | timestamp decoded as Long | Type loss |
| 6 | ProtonJ2 | binary/timestamp wrong in lists | Data corruption |
| 7 | ProtonJ2 | Cannot send binary correlation ID | Missing feature |
| 8 | Proton .NET | Cannot send binary correlation ID | Missing feature |
| 9 | Proton .NET | timestamp decoded as Int64 | Type loss |
| 10 | Proton .NET | byte[] in lists encoded as array | Data corruption |
| 11 | Proton .NET | ubyte array decoded as binary | Type loss |
| 12 | Proton .NET | empty binary round-trip type loss | Type loss |
| 13 | Proton .NET→ProtonJ2 | binary encoding incompatible | Interop failure |
| 14 | Rhea | 64-bit integer precision loss | Data corruption |