juicedata/juicefs · error

failed to read segment value: err %v, read len %d, expect le

Error message

failed to read segment value: err %v, read len %d, expect len %d

What it means

After reading the segment length, BakSegment.Unmarshal allocates a buffer of s.len bytes and reads the payload with a single r.Read call. This error is thrown when the read fails or returns fewer bytes than s.len, meaning the segment payload is truncated or the stream is unreadable. Note the guard `err != nil && n != int(s.len)` means a short read with nil error is silently accepted (io.Reader contract violation by the source), while any error with an incomplete read produces this message.

Source

Thrown at pkg/meta/backup.go:364

	return binary.Size(s.typ) + binary.Size(s.len) + len(data), nil
}

func (s *BakSegment) Unmarshal(r io.Reader) error {
	if err := binary.Read(r, binary.BigEndian, &s.typ); err != nil {
		return fmt.Errorf("failed to read segment type: %v", err)
	}

	if s.typ == BakEOS {
		return errBakEOF
	}

	if err := binary.Read(r, binary.BigEndian, &s.len); err != nil {
		return fmt.Errorf("failed to read segment %s length: %v", s, err)
	}
	data := make([]byte, s.len)
	n, err := r.Read(data)
	if err != nil && n != int(s.len) {
		return fmt.Errorf("failed to read segment value: err %v, read len %d, expect len %d", err, n, s.len)
	}

	msg, err := getMessageFromType(int(s.typ))
	if err != nil {
		return fmt.Errorf("failed to create message by type %d: %w", s.typ, err)
	}
	if err = proto.Unmarshal(data, msg); err != nil {
		return fmt.Errorf("failed to unmarshal segment msg %d: %w", s.typ, err)
	}
	s.val = msg
	return nil
}

type DumpOption struct {
	KeepSecret bool
	Threads    int
	Progress   func(name string, cnt int)
}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Regenerate the backup — a truncated payload means the footer cannot be trusted
  2. Compare the backup file size/checksum with the source to confirm truncation and fix the transfer
  3. Check the health of the storage backing the backup (disk errors, mount stability)
  4. If a custom io.Reader is the source, fix it to fill the buffer or return io.ErrUnexpectedEOF on short reads

Example fix

// before (caller-side, more robust read)
n, err := r.Read(data)
// after (read fully)
if _, err := io.ReadFull(r, data); err != nil {
    return fmt.Errorf("failed to read segment value: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

fi, err := os.Stat(backupPath)
if err != nil { return err } // then compare fi.Size() against bytes already consumed before trusting remaining payload

Try / catch

if err := seg.Unmarshal(r); err != nil {
    if strings.Contains(err.Error(), "failed to read segment value") {
        return fmt.Errorf("backup payload truncated, regenerate backup: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ReadFooter on a stream whose segment payload is cut short: backup truncated mid-segment, corrupted file, or an I/O error (device failure, closed handle) during payload read; also a giant/corrupt s.len making the expected length unreachable.

Common situations: Metadata backup interrupted by crash or disk-full mid-segment; file transferred incompletely (e.g., partial upload/download); reading a backup over an unreliable mount that returns errors mid-read.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/c2faec155f223180. Report an issue: GitHub.