v2rayA/v2rayA · error
read frame body: %w
Error message
read frame body: %w
What it means
While scanning a .dat geosite file frame-by-frame, io.ReadFull failed to read the announced bodyLen bytes of a frame body. The file is either truncated/corrupt or the framing is wrong, so loadGeositeTag aborts reading this file.
Source
Thrown at core/main/geosite.go:144
}
if tagByte != 0x0a {
// Not the expected frame format — skip.
continue
}
// Read the varint length of the message body.
bodyLen, err := binary.ReadUvarint(br)
if err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("read frame length: %w", err)
}
// Read the message body.
body := make([]byte, bodyLen)
if _, err := io.ReadFull(br, body); err != nil {
return nil, fmt.Errorf("read frame body: %w", err)
}
// Unmarshal as GeoSite and check code.
var site geodata.GeoSite
if err := proto.Unmarshal(body, &site); err != nil {
// Skip entries we can't parse.
continue
}
if site.Code != tag && site.Code != tagUpper {
continue
}
// Found matching entry — cache and return.
domains := site.Domain
geositeCache.mu.Lock()
geositeCache.data[cacheKey] = domains
geositeCache.mu.Unlock()View on GitHub (pinned to 71e5442fc5)
Solutions
- Re-download / replace the geosite .dat file with a fresh, complete copy
- Verify file size and checksum against the official release
- Rebuild the .dat from source with a matching geodata protocol version
- Check the configured geosite path points to the intended file, not a truncated leftover
Example fix
// before
body := make([]byte, bodyLen)
if _, err := io.ReadFull(br, body); err != nil {
return nil, fmt.Errorf("read frame body: %w", err)
}
// after
// redeploy a complete geosite.dat first, e.g.:
// curl -fLo geosite.dat https://example.com/geosite.dat && sha256sum -c geosite.dat.sha256
body := make([]byte, bodyLen)
if _, err := io.ReadFull(br, body); err != nil {
return nil, fmt.Errorf("read frame body (file may be truncated/corrupt): %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// verify the geosite file before loading
st, err := os.Stat(geositePath)
if err != nil || st.Size() < 1024 { return fmt.Errorf("geosite file missing or truncated: %s", geositePath) }
// optional: verify sha256 against the release checksum Try / catch
tags, err := loadGeositeTag(path, tag)
if err != nil {
if strings.Contains(err.Error(), "read frame") {
// file corrupt: re-download before giving up
}
return nil, err
} Prevention
- Verify checksums of geosite.dat after download
- Download atomically (tmp file + rename) to avoid partial files
- Pin a known-good geosite.dat version in deployments
- Handle read errors by re-fetching the data file automatically
When it happens
Trigger: io.ReadFull(br, body) returns fewer than bodyLen bytes: the geosite .dat file was truncated during download, is corrupt on disk, or the declared frame length exceeds remaining file data.
Common situations: Interrupted download of geosite.dat left a partial file; disk corruption; a custom-built geosite.dat produced with a mismatched protobuf/framing version; mounted file cut short in a container image.
Related errors
- dns unpack: %w
- tag %q not found in %s
- UpdateLocalGeoSite: damaged GFWList file, update it again pl
- damaged GFWList file, update it again please
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/8cb0f690796ee1d7.
Report an issue: GitHub.