{"record":{"id":"cd66b6de4300b5b8","repo":"openzipkin/zipkin","slug":"malformed-invalid-boolean-value-at-byte","errorCode":null,"errorMessage":"Malformed: invalid boolean value at byte ","messagePattern":"Malformed: invalid boolean value at byte ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/internal/Proto3Fields.java","lineNumber":265,"sourceCode":"    BooleanField(int key) {\n      super(key);\n      assert wireType == WIRETYPE_VARINT;\n    }\n\n    int sizeInBytes(boolean bool) {\n      return bool ? 2 : 0; // tag + varint\n    }\n\n    void write(WriteBuffer b, boolean bool) {\n      if (!bool) return;\n      b.writeByte(key);\n      b.writeByte(1);\n    }\n\n    boolean read(ReadBuffer b) {\n      byte bool = b.readByte();\n      if (bool < 0 || bool > 1) {\n        throw new IllegalArgumentException(\"Malformed: invalid boolean value at byte \" + b.pos());\n      }\n      return bool == 1;\n    }\n  }\n\n  // added for completion as later we will skip fields we don't use\n  static final class Fixed32Field extends Field {\n    Fixed32Field(int key) {\n      super(key);\n      assert wireType == WIRETYPE_FIXED32;\n    }\n\n    int sizeInBytes(int number) {\n      if (number == 0) return 0;\n      return 1 + 4; // tag + 4 byte number\n    }\n  }\n","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java#L247-L283","documentation":"In proto3, a bool field is a single varint byte that must be 0 or 1. Proto3Fields.BoolField.read throws 'Malformed: invalid boolean value at byte N' when it reads a byte outside that range (e.g. 2..255 or a negative byte). This points to a producer encoding booleans incorrectly or, again, a misaligned stream.","triggerScenarios":"Decoding a proto3 Span whose 'debug' or 'shared' field (bool fields in zipkin2.proto) contains a varint other than 0/1, e.g. a truncated two-byte varint where the second byte is read as the bool.","commonSituations":"Custom encoders writing boolean flags as multi-byte varints or as raw integers; schema drift where a non-bool field's bytes are read as bool after misalignment; fuzzed payloads.","solutions":["Check the byte offset in the message; verify the bytes immediately before it (the field tag) match the expected bool field key.","Ensure producers encode bools as exactly one byte (0x00/0x01) — prefer SpanBytesEncoder.PROTO3.","If interoperating with protoc-based clients, confirm they use the official zipkin2.proto and do not pack bools into varints > 1 byte.","Reject/quarantine the message in collector code; do not retry it, deterministic corruption will not heal."],"exampleFix":"// before\n// hand-rolled: wrote debug flag as int varint\nwriteVarint(debug ? 2 : 0);\n\n// after\n// proto3 bool: single byte, 1 or 0\nbuffer.writeByte(key);\nbuffer.writeByte(debug ? 1 : 0);","handlingStrategy":"validation","validationCode":"// if you control the bytes, assert the bool byte before decode is impractical; instead validate at encode time\nvoid writeBool(WriteBuffer b, int key, boolean v) { b.writeByte(key); b.writeByte(v ? 1 : 0); }","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) { if (e.getMessage().contains(\"invalid boolean\")) { LOG.warn(\"bad bool encoding from producer\"); drop(); } else throw e; }","preventionTips":["Encode proto3 bools as a single byte 0/1 only.","Use protoc-generated classes for cross-language producers.","Fuzz your collector with random bytes in staging to verify graceful drops."],"tags":["zipkin","protobuf","boolean","malformed"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}