{"record":{"id":"54c17fe28d5d76c3","repo":"gchq/CyberChef","slug":"unknown-type-0x-type-tostring-16","errorCode":null,"errorMessage":"Unknown type 0x${type.toString(16)}","messagePattern":"Unknown type 0x(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/lib/Protobuf.mjs","lineNumber":434,"sourceCode":"            this.fieldTypes[key] = type;\n        }\n\n        switch (type) {\n            // varint\n            case 0:\n                return { \"key\": key, \"value\": this._varInt() };\n            // fixed 64\n            case 1:\n                return { \"key\": key, \"value\": this._uint64() };\n            // length delimited\n            case 2:\n                return { \"key\": key, \"value\": this._lenDelim(key) };\n            // fixed 32\n            case 5:\n                return { \"key\": key, \"value\": this._uint32() };\n            // unknown type\n            default:\n                throw new Error(\"Unknown type 0x\" + type.toString(16));\n        }\n    }\n\n    /**\n     * Parse the field header and return the type and key\n     *\n     * @private\n     * @returns {Object}\n     */\n    _fieldHeader() {\n        // Make sure we call type then number to preserve offset\n        return { \"type\": this._fieldType(), \"key\": this._fieldNumber() };\n    }\n\n    /**\n     * Parse the field type from the field header. Type is stored in the\n     * lower 3 bits of the tag byte. This does not move the offset on as\n     * we need to read the field number from the tag byte too.","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Protobuf.mjs#L416-L452","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm the data was produced by a conformant proto3/proto2 encoder that does not use groups.","Re-check earlier field parsing — a wrong length/varint earlier shifts the offset into garbage.","If groups are genuinely needed, pre-convert the payload to length-delimited form with another tool."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const SUPPORTED_WIRE = new Set([0, 1, 2, 5]);\nfunction supportedWireTypes(bytes) {\n  // best-effort: walk tags and check low 3 bits\n  const pb = new Protobuf(bytes);\n  try { return pb._parse(), true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return new Protobuf(input)._parse();\n} catch (e) {\n  if (/Unknown type 0x/.test(e.message)) {\n    // likely groups (3/4) or offset corruption — re-verify earlier fields\n  }\n  throw e;\n}","preventionTips":["Encode with proto3/proto2 encoders that do not emit groups.","Treat 'Unknown type' as a signal of offset drift from an earlier malformed field.","Cross-check the bytes against a reference decoder (e.g. protoc --decode_raw)."],"tags":["protobuf","decode","wire-type","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}