mudler/LocalAI · error
bytesToInt16sLE: input bytes slice has odd length, must be e
Error message
bytesToInt16sLE: input bytes slice has odd length, must be even
What it means
Panic in pkg/sound BytesToInt16sLE when the input byte slice has an odd number of bytes. The function reinterprets bytes as little-endian int16 pairs (two bytes per sample), so an odd length means half a sample — usually a truncated audio buffer — and rather than silently drop a byte it panics.
Source
Thrown at pkg/sound/int16.go:82
// Linearly interpolate between the two surrounding input samples
output[i] = int16((1-frac)*float64(input[indexBefore]) + frac*float64(input[indexAfter]))
}
return output
}
func ConvertInt16ToInt(input []int16) []int {
output := make([]int, len(input)) // Allocate a slice for the output
for i, value := range input {
output[i] = int(value) // Convert each int16 to int and assign it to the output slice
}
return output // Return the converted slice
}
func BytesToInt16sLE(bytes []byte) []int16 {
// Ensure the byte slice length is even
if len(bytes)%2 != 0 {
panic("bytesToInt16sLE: input bytes slice has odd length, must be even")
}
int16s := make([]int16, len(bytes)/2)
for i := range len(int16s) {
int16s[i] = int16(bytes[2*i]) | int16(bytes[2*i+1])<<8
}
return int16s
}
func Int16toBytesLE(arr []int16) []byte {
le := binary.LittleEndian
result := make([]byte, 0, 2*len(arr))
for _, val := range arr {
result = le.AppendUint16(result, uint16(val))
}
return result
}
View on GitHub (pinned to 44413a9d06)
Solutions
- Trim to even length before calling: process buf[:len(buf)-len(buf)%2] and carry the leftover byte into the next chunk
- For streams, buffer bytes and only convert when >=2 bytes are available, keeping the remainder
- Check upstream for truncation: verify the producer is sending whole PCM16 frames
- Use Int16toBytesLE / matching helpers on the producer side so lengths stay multiples of two
Example fix
// before
samples := sound.BytesToInt16sLE(chunk) // panics on odd chunk
// after
if odd := len(chunk) % 2; odd != 0 {
chunk = chunk[:len(chunk)-1] // or stash last byte for next chunk
}
samples := sound.BytesToInt16sLE(chunk) Defensive patterns
Strategy: validation
Validate before calling
func toInt16Safe(b []byte) ([]int16, []byte) {
n := len(b) - len(b)%2
return sound.BytesToInt16sLE(b[:n]), b[n:]
} Type guard
func isEvenLength(b []byte) bool { return len(b)%2 == 0 } Try / catch
// panics in Go; if the boundary is untrusted, wrap it
func safeBytesToInt16sLE(b []byte) (out []int16, err error) {
defer func() { if r := recover(); r != nil { err = fmt.Errorf("odd byte length: %d", len(b)) } }()
return sound.BytesToInt16sLE(b), nil
} Prevention
- Always frame PCM16 streams in whole-sample (2-byte) chunks
- Carry leftover odd bytes into the next chunk in streaming loops
- Log byte counts at chunk boundaries to catch truncation early
When it happens
Trigger: Feeding PCM16 audio whose length is not a multiple of 2: a chunked stream split mid-sample, a buffer sliced with an off-by-one, or raw bytes from a source that includes a header/odd-sized footer concatenated with samples.
Common situations: Streaming TTS/ASR pipelines that chunk audio at arbitrary byte boundaries; mixing mono/stereo or headered formats (WAV headers stripped incorrectly); len(buf)-1 style slicing bugs; network reads returning partial frames.
Related errors
- voiceCreate.audio.durationError
- audio is required for LongCat-Video-Avatar-1.5
- audio contains no samples
- request needs {segments} avatar segments, but max_segments i
- router/rerank: policy has empty label
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/a106cdf79662a7c0.
Report an issue: GitHub.