openzipkin/zipkin · error · IllegalArgumentException

Malformed: invalid boolean value at byte

Error message

Malformed: invalid boolean value at byte 

What it means

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.

Source

Thrown at zipkin/src/main/java/zipkin2/internal/Proto3Fields.java:265

    BooleanField(int key) {
      super(key);
      assert wireType == WIRETYPE_VARINT;
    }

    int sizeInBytes(boolean bool) {
      return bool ? 2 : 0; // tag + varint
    }

    void write(WriteBuffer b, boolean bool) {
      if (!bool) return;
      b.writeByte(key);
      b.writeByte(1);
    }

    boolean read(ReadBuffer b) {
      byte bool = b.readByte();
      if (bool < 0 || bool > 1) {
        throw new IllegalArgumentException("Malformed: invalid boolean value at byte " + b.pos());
      }
      return bool == 1;
    }
  }

  // added for completion as later we will skip fields we don't use
  static final class Fixed32Field extends Field {
    Fixed32Field(int key) {
      super(key);
      assert wireType == WIRETYPE_FIXED32;
    }

    int sizeInBytes(int number) {
      if (number == 0) return 0;
      return 1 + 4; // tag + 4 byte number
    }
  }

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Check the byte offset in the message; verify the bytes immediately before it (the field tag) match the expected bool field key.
  2. Ensure producers encode bools as exactly one byte (0x00/0x01) — prefer SpanBytesEncoder.PROTO3.
  3. If interoperating with protoc-based clients, confirm they use the official zipkin2.proto and do not pack bools into varints > 1 byte.
  4. Reject/quarantine the message in collector code; do not retry it, deterministic corruption will not heal.

Example fix

// before
// hand-rolled: wrote debug flag as int varint
writeVarint(debug ? 2 : 0);

// after
// proto3 bool: single byte, 1 or 0
buffer.writeByte(key);
buffer.writeByte(debug ? 1 : 0);
Defensive patterns

Strategy: validation

Validate before calling

// if you control the bytes, assert the bool byte before decode is impractical; instead validate at encode time
void writeBool(WriteBuffer b, int key, boolean v) { b.writeByte(key); b.writeByte(v ? 1 : 0); }

Try / catch

catch (IllegalArgumentException e) { if (e.getMessage().contains("invalid boolean")) { LOG.warn("bad bool encoding from producer"); drop(); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/cd66b6de4300b5b8. Report an issue: GitHub.