gchq/CyberChef · error · Error

Unknown type 0x${type.toString(16)}

Error message

Unknown type 0x${type.toString(16)}

What it means

Thrown by Protobuf._parseFieldType when the low 3 bits of a field tag (the wire type) are not one of the implemented cases (0 varint, 1 fixed64, 2 length-delimited, 5 fixed32). Wire types 3 and 4 (start/end group) are deprecated and intentionally unsupported here; 6/7 are reserved and illegal.

Source

Thrown at src/core/lib/Protobuf.mjs:434

            this.fieldTypes[key] = type;
        }

        switch (type) {
            // varint
            case 0:
                return { "key": key, "value": this._varInt() };
            // fixed 64
            case 1:
                return { "key": key, "value": this._uint64() };
            // length delimited
            case 2:
                return { "key": key, "value": this._lenDelim(key) };
            // fixed 32
            case 5:
                return { "key": key, "value": this._uint32() };
            // unknown type
            default:
                throw new Error("Unknown type 0x" + type.toString(16));
        }
    }

    /**
     * Parse the field header and return the type and key
     *
     * @private
     * @returns {Object}
     */
    _fieldHeader() {
        // Make sure we call type then number to preserve offset
        return { "type": this._fieldType(), "key": this._fieldNumber() };
    }

    /**
     * Parse the field type from the field header. Type is stored in the
     * lower 3 bits of the tag byte. This does not move the offset on as
     * we need to read the field number from the tag byte too.

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Confirm the data was produced by a conformant proto3/proto2 encoder that does not use groups.
  2. Re-check earlier field parsing — a wrong length/varint earlier shifts the offset into garbage.
  3. If groups are genuinely needed, pre-convert the payload to length-delimited form with another tool.
Defensive patterns

Strategy: try-catch

Validate before calling

const SUPPORTED_WIRE = new Set([0, 1, 2, 5]);
function supportedWireTypes(bytes) {
  // best-effort: walk tags and check low 3 bits
  const pb = new Protobuf(bytes);
  try { return pb._parse(), true; } catch { return false; }
}

Try / catch

try {
  return new Protobuf(input)._parse();
} catch (e) {
  if (/Unknown type 0x/.test(e.message)) {
    // likely groups (3/4) or offset corruption — re-verify earlier fields
  }
  throw e;
}

Prevention

When it happens

Trigger: Decoding bytes whose field tag's wire type is 3, 4, 6, or 7; mis-aligned offset causing a data byte to be read as a tag; decoding a payload that uses legacy group encoding; non-protobuf input that randomly hits these bits.

Common situations: Older protobuf encoders that still emit groups; offset corruption from a prior malformed field; random binary mistaken for protobuf; a length prefix misread so the cursor lands mid-field.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/54c17fe28d5d76c3. Report an issue: GitHub.