{"record":{"id":"cd7b278474c470d9","repo":"openzipkin/zipkin","slug":"malformed-fieldnumber-was-zero-at-byte","errorCode":null,"errorMessage":"Malformed: fieldNumber was zero at byte ","messagePattern":"Malformed: fieldNumber was zero at byte ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/internal/Proto3Fields.java","lineNumber":52,"sourceCode":"     *\n     * <p>See https://developers.google.com/protocol-buffers/docs/encoding#structure\n     */\n    final int key;\n\n    Field(int key) {\n      this(key >>> 3, key & (1 << 3) - 1, key);\n    }\n\n    Field(int fieldNumber, int wireType, int key) {\n      this.fieldNumber = fieldNumber;\n      this.wireType = wireType;\n      this.key = key;\n    }\n\n    static int fieldNumber(int key, int byteL) {\n      int fieldNumber = key >>> 3;\n      if (fieldNumber != 0) return fieldNumber;\n      throw new IllegalArgumentException(\"Malformed: fieldNumber was zero at byte \" + byteL);\n    }\n\n    static int wireType(int key, int byteL) {\n      int wireType = key & (1 << 3) - 1;\n      if (wireType != 0 && wireType != 1 && wireType != 2 && wireType != 5) {\n        throw new IllegalArgumentException(\n          \"Malformed: invalid wireType \" + wireType + \" at byte \" + byteL);\n      }\n      return wireType;\n    }\n\n    static boolean skipValue(ReadBuffer buffer, int wireType) {\n      int remaining = buffer.available();\n      switch (wireType) {\n        case WIRETYPE_VARINT:\n          for (int i = 0; i < remaining; i++) {\n            if (buffer.readByte() >= 0) return true;\n          }","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java#L34-L70","documentation":"Protobuf field keys are varints where fieldNumber = key >>> 3; a key whose top 3 bits of the tag (the field number portion) are zero is invalid, because field numbers start at 1. Proto3Fields.Field.fieldNumber throws 'Malformed: fieldNumber was zero at byte N' (with the byte offset) when it decodes such a key while reading a span. This almost always means the byte stream is not the expected protobuf message.","triggerScenarios":"PROTO3 decoding of bytes where a tag varint decodes to 0 (e.g. leading zero bytes) or where the stream has drifted out of sync — typically after an earlier field was mis-skipped, or when raw non-proto bytes are fed to Proto3SpanReader.","commonSituations":"Payload prefixed/padded with zero bytes; JSON bytes sent to a proto3 endpoint; an earlier unknown field with a bad length shifted the reader so the next 'tag' lands mid-value; manually constructed test fixtures with wrong tag bytes.","solutions":["Check the cause chain: an earlier decode error usually preceded this; look at the reported byte offset and dump the bytes around it.","Verify the payload starts with a valid length-delimited field key (0x0a for field 1, e.g.) and that the producer uses zipkin2.proto3 Span encoding.","Strip framing/padding bugs (extra NUL bytes, length prefixes applied twice) at the producer.","Round-trip test: SpanBytesEncoder.PROTO3.encode(span) then decode, to confirm your pipeline handles well-formed proto3."],"exampleFix":"// before\nbyte[] payload = message.getBody(); // raw bytes from a queue\nSpan span = SpanBytesDecoder.PROTO3.decodeOne(payload);\n\n// after\nbyte[] payload = message.getBody();\nif (payload.length == 0 || payload[0] == 0) {\n  throw new IllegalArgumentException(\"payload is not proto3 (leading zero/NUL byte)\");\n}\nSpan span = SpanBytesDecoder.PROTO3.decodeOne(payload);","handlingStrategy":"validation","validationCode":"// cheap sanity check: a zipkin proto3 span list starts with field-1 length-delimited tag 0x0a\nboolean looksLikeZipkinProto3(byte[] b) { return b.length > 2 && b[0] == 0x0a; }","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) { if (e.getMessage().contains(\"fieldNumber was zero\")) dropAsNonProto3(payload); else throw e; }","preventionTips":["Never NUL-pad or prefix proto3 payloads.","Verify framing (single length prefix, applied once) between producer and queue.","Keep a hex dump utility handy in collector logs for offset diagnosis."],"tags":["zipkin","protobuf","malformed","decoding"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}