{"record":{"id":"b6f98d0032093e7a","repo":"dagger/dagger","slug":"decode-length-varint-overflow","errorCode":null,"errorMessage":"decode length: varint overflow","messagePattern":"decode length: varint overflow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/clientdb/store_codec.go","lineNumber":99,"sourceCode":"\tv := d.buf[d.off]\n\td.off++\n\tswitch v {\n\tcase 0:\n\t\treturn false, nil\n\tcase 1:\n\t\treturn true, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"decode bool: invalid value %d\", v)\n\t}\n}\n\nfunc (d *rowDecoder) length() (int, error) {\n\tv, n := binary.Uvarint(d.buf[d.off:])\n\tif n == 0 {\n\t\treturn 0, fmt.Errorf(\"decode length: truncated varint\")\n\t}\n\tif n < 0 {\n\t\treturn 0, fmt.Errorf(\"decode length: varint overflow\")\n\t}\n\td.off += n\n\tif v > uint64(maxInt) {\n\t\treturn 0, fmt.Errorf(\"decode length: %d overflows int\", v)\n\t}\n\treturn int(v), nil\n}\n\nfunc (d *rowDecoder) take(n int) ([]byte, error) {\n\tif n < 0 || n > len(d.buf)-d.off {\n\t\treturn nil, fmt.Errorf(\"decode field of length %d: only %d bytes remain\", n, len(d.buf)-d.off)\n\t}\n\tv := d.buf[d.off : d.off+n]\n\td.off += n\n\treturn v, nil\n}\n\nfunc (d *rowDecoder) string() (string, error) {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/clientdb/store_codec.go#L81-L117","documentation":"rowDecoder.length returns this when binary.Uvarint returns n<0, meaning the length varint exceeds its maximum byte width (malformed encoding, more than 10 bytes). The bytes at the offset are not a valid unsigned varint, so the row data or the decode offset is wrong.","triggerScenarios":"rowDecoder.string/bytes decoding a row where the length-prefix position holds non-varint bytes — wrong field order in the decoder, decoding a bytes field where an int64 (signed varint, different encoding) was written, or corrupt data.","commonSituations":"Writer/reader codec drift (field types swapped between versions); misaligned offset from an earlier field decoded with the wrong width; damaged local trace store.","solutions":["Compare decoder field order/types with the encoder byte-for-byte; fix any swapped or missing fields.","Remember binary.Varint (signed, for int64) and binary.Uvarint (unsigned, for lengths) are different encodings — ensure lengths are written with PutUvarint.","Hex-dump the row and decode by hand to confirm whether the offset or the data is at fault.","Add a per-row checksum so malformed encodings are rejected at load time instead of mid-decode."],"exampleFix":"// before\nbinary.PutVarint(buf, int64(len(s))) // signed varint for a length\n// after\nbinary.PutUvarint(buf, uint64(len(s))) // lengths must use Uvarint","handlingStrategy":"validation","validationCode":"if _, n := binary.Uvarint(buf[off:]); n < 0 {\n    return fmt.Errorf(\"malformed length varint at offset %d\", off)\n}","typeGuard":null,"tryCatchPattern":"n, err := dec.length()\nif err != nil {\n    return nil, fmt.Errorf(\"bad length prefix: %w\", err)\n}","preventionTips":["Write length prefixes with binary.PutUvarint (unsigned), not PutVarint.","Match decoder reads to encoder writes field-for-field.","Version-stamp rows to prevent cross-version misdecoding."],"tags":["go","codec","varint","corruption"],"backgroundTag":"varint-overflow","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}