benbjohnson/litestream · warning
invalid wal segment path: %s: %w
Error message
invalid wal segment path: %s: %w
What it means
In ParseWALSegmentFilenameV3, once the filename matches the regex, the first capture (WAL index) is parsed with strconv.ParseInt(m[1], 16, 32). This error wraps a failure of that conversion. It can only fire when the matched hex string cannot be represented in a 32-bit signed integer, since the regex guarantees hex digits.
Source
Thrown at v3.go:138
return 0, fmt.Errorf("invalid v0.3.x snapshot filename: %q", filename)
}
idx, err := strconv.ParseInt(m[1], 16, 32)
if err != nil {
return 0, fmt.Errorf("invalid snapshot path: %s: %w", filename, err)
}
return int(idx), nil
}
// ParseWALSegmentFilenameV3 parses a v0.3.x WAL segment filename.
// Returns the WAL index and byte offset, or an error if the filename is invalid.
func ParseWALSegmentFilenameV3(filename string) (index int, offset int64, err error) {
m := walSegmentRegexV3.FindStringSubmatch(filename)
if m == nil {
return 0, 0, fmt.Errorf("invalid v0.3.x WAL segment filename: %q", filename)
}
idx, err := strconv.ParseInt(m[1], 16, 32)
if err != nil {
return 0, 0, fmt.Errorf("invalid wal segment path: %s: %w", filename, err)
}
off, err := strconv.ParseInt(m[2], 16, 64)
if err != nil {
return 0, 0, fmt.Errorf("invalid wal segment path: %s: %w", filename, err)
}
return int(idx), off, nil
}
// IsGenerationIDV3 returns true if s is a valid v0.3.x generation ID (16 hex chars).
func IsGenerationIDV3(s string) bool {
return generationRegexV3.MatchString(s)
}
// ReplicaClientV3 reads v0.3.x backup data.
// ReplicaClient implementations that support v0.3.x restore should implement this interface.
type ReplicaClientV3 interface {
// GenerationsV3 returns a list of generation IDs in the replica.
// Returns an empty slice if no v0.3.x backups exist.View on GitHub (pinned to 4ed7a308f6)
Solutions
- Run Litestream/tooling on a 64-bit platform (amd64, arm64) so int can hold indexes up to 0xFFFFFFFF.
- Check that the segment filename was not tampered with; genuine v0.3.x indexes stay within 8 hex digits.
- If you must support 32-bit, parse the index yourself with ParseInt(m[1], 16, 64) before calling the library.
Defensive patterns
Strategy: type-guard
Validate before calling
func walIndexFits32Bit(hexIdx string) bool {
v, err := strconv.ParseInt(hexIdx, 16, 64)
return err == nil && v >= 0 && v <= math.MaxInt32
} Type guard
func fitsInt32(v int64) bool { return v >= math.MinInt32 && v <= math.MaxInt32 } Try / catch
idx, off, err := litestream.ParseWALSegmentFilenameV3(name)
var numErr *strconv.NumError
if errors.As(err, &numErr) && errors.Is(numErr.Err, strconv.ErrRange) {
return switchTo64BitRuntime()
} Prevention
- Build/parse on 64-bit platforms
- Cap replica scanning at segments with indexes within int32 range on 32-bit hosts
- Validate hex index magnitude before invoking the parser on 32-bit systems
When it happens
Trigger: Parsing a WAL segment whose 8-hex-digit index exceeds 0x7FFFFFFF on a platform where int is 32 bits; ParseInt(m[1], 16, 32) returns a range error which is wrapped here.
Common situations: 32-bit builds (arm, 386) processing replicas with very high WAL indexes; essentially unreachable on 64-bit platforms.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- invalid snapshot path: %s: %w
- set synchronous: %w
- checkpoint: %w
- checkpoint failed: %w
- sync database %s: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/be14d5423a47aebd.
Report an issue: GitHub.