{"record":{"id":"ca4d2a0c735be851","repo":"vitessio/vitess","slug":"metadatalength-unhandled-data-type-v","errorCode":null,"errorMessage":"metadataLength: unhandled data type: %v","messagePattern":"metadataLength: unhandled data type: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/binlog_event_rbr.go","lineNumber":154,"sourceCode":"\tcase binlog.TypeDecimal, binlog.TypeTiny, binlog.TypeShort, binlog.TypeLong, binlog.TypeNull, binlog.TypeTimestamp, binlog.TypeLongLong, binlog.TypeInt24, binlog.TypeDate, binlog.TypeTime, binlog.TypeDateTime, binlog.TypeYear, binlog.TypeNewDate:\n\t\t// No data here.\n\t\treturn 0\n\n\tcase binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector:\n\t\t// One byte.\n\t\treturn 1\n\n\tcase binlog.TypeNewDecimal, binlog.TypeEnum, binlog.TypeSet, binlog.TypeString:\n\t\t// Two bytes, Big Endian because of crazy encoding.\n\t\treturn 2\n\n\tcase binlog.TypeVarchar, binlog.TypeBit, binlog.TypeVarString:\n\t\t// Two bytes, Little Endian\n\t\treturn 2\n\n\tdefault:\n\t\t// Unknown type. This is used in tests only, so panic.\n\t\tpanic(vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"metadataLength: unhandled data type: %v\", typ))\n\t}\n}\n\n// metadataTotalLength returns the total size of the metadata for an\n// array of types.\nfunc metadataTotalLength(types []byte) int {\n\tsum := 0\n\tfor _, t := range types {\n\t\tsum += metadataLength(t)\n\t}\n\treturn sum\n}\n\n// metadataRead reads a single value from the metadata string.\nfunc metadataRead(data []byte, pos int, typ byte) (uint16, int, error) {\n\tswitch typ {\n\tcase binlog.TypeDecimal, binlog.TypeTiny, binlog.TypeShort, binlog.TypeLong, binlog.TypeNull, binlog.TypeTimestamp, binlog.TypeLongLong, binlog.TypeInt24, binlog.TypeDate, binlog.TypeTime, binlog.TypeDateTime, binlog.TypeYear, binlog.TypeNewDate:\n\t\t// No data here.","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/binlog_event_rbr.go#L136-L172","documentation":"metadataLength computes the byte size of the optional metadata for a column type; for unrecognized types it panics with a vterrors INTERNAL error, since this path is expected only in tests with synthetic types. Valid production binlog types never reach the default branch.","triggerScenarios":"Calling NewTableMapEvent (via metadataTotalLength -> metadataLength) with a TableMap.Types entry containing a byte that is not a supported MySQL column type.","commonSituations":"Unit tests using made-up type bytes; corrupted or truncated binlog data supplying invalid type codes; new upstream MySQL types not yet added to the switch.","solutions":["Replace the unsupported type byte with a valid binlog.Type* constant.","Add the missing type to metadataLength (and the matching read/write functions) if it is a real new MySQL type.","Sanitize the TableMap before building events, rejecting unknown type codes with a proper error."],"exampleFix":"// before\ntm.Types = []byte{0x99} // unknown\nev := mysql.NewTableMapEvent(f, s, id, tm) // panics\n// after\ntm.Types = []byte{binlog.TypeFloat}\nev := mysql.NewTableMapEvent(f, s, id, tm)","handlingStrategy":"validation","validationCode":"for _, typ := range tm.Types {\n    if !isKnownBinlogType(typ) {\n        return errors.Errorf(\"unknown column type %d before building table map\", typ)\n    }\n}","typeGuard":null,"tryCatchPattern":"func safeMetadataTotal(types []byte) (n int, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"metadataLength: %v\", r)\n        }\n    }()\n    return mysql.MetadataTotalLength(types), nil\n}","preventionTips":["Whitelist column types against binlog.Type* constants before constructing events.","When new MySQL versions add types, extend metadataLength/metadataWrite/metadataRead in the same change.","In tests, avoid inventing type bytes; reuse constants from the binlog package."],"tags":["mysql","binlog","panics","internal"],"backgroundTag":"unhandled-column-type","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}