spicetify/cli · error
invalid UTF-16LE data length
Error message
invalid UTF-16LE data length
What it means
decodeUTF16LE converts a UTF-16LE byte slice to UTF-8 by reinterpreting every 2 bytes as one uint16 code unit. It returns "invalid UTF-16LE data length" when the input length is odd, because a truncated final code unit cannot be decoded. It is internal, so callers see it wrapped as "error decoding UTF-16LE content" from ReadStringFromUTF16Binary.
Source
Thrown at src/utils/file-utils.go:76
originalEndIdx := 2 + endIdx + len(stringContentBytes)
return string(decodedStringBytes), originalStartIdx, originalEndIdx, nil
}
// Helper function to encode a byte slice (assumed UTF-8) to UTF-16LE
func encodeUTF16LE(data []byte) []byte {
utf16Bytes := utf16.Encode([]rune(string(data)))
byteSlice := make([]byte, len(utf16Bytes)*2)
for i, r := range utf16Bytes {
binary.LittleEndian.PutUint16(byteSlice[i*2:], r)
}
return byteSlice
}
// Helper function to decode a byte slice (UTF-16LE) to UTF-8
func decodeUTF16LE(data []byte) ([]byte, error) {
if len(data)%2 != 0 {
return nil, fmt.Errorf("invalid UTF-16LE data length")
}
uint16s := make([]uint16, len(data)/2)
for i := 0; i < len(data)/2; i++ {
uint16s[i] = binary.LittleEndian.Uint16(data[i*2:])
}
runes := utf16.Decode(uint16s)
return []byte(string(runes)), nil
}
View on GitHub (pinned to 1f13f73616)
Solutions
- Check the length of the data region: it must be even (each UTF-16 code unit is 2 bytes) before decoding.
- Verify the file is not truncated — compare its size against the expected full record and re-download/re-export if short.
- Ensure start and end markers do not overlap and appear exactly once so the extracted slice boundaries are aligned.
- If you own the data producer, guarantee even-length output; otherwise strip or repair the trailing odd byte before parsing.
Example fix
// before
decoded, err := decodeUTF16LE(region)
// after
if len(region)%2 != 0 {
region = region[:len(region)-1] // or repair/re-fetch the source file
}
decoded, err := decodeUTF16LE(region) Defensive patterns
Strategy: validation
Validate before calling
func validUTF16LE(data []byte) bool {
return data != nil && len(data)%2 == 0
} Type guard
// Go: guard on error text from the wrapped error
func isInvalidUTF16Length(err error) bool {
return err != nil && strings.Contains(err.Error(), "invalid UTF-16LE data length")
} Try / catch
if err != nil {
if isInvalidUTF16Length(err) {
// treat as corrupt input; skip or repair
return "", ErrCorruptPrefs
}
return err
} Prevention
- Always assert len(data)%2 == 0 before decoding UTF-16 data you slice yourself.
- Check file size parity (after the 2-byte BOM) as an integrity signal.
- Avoid slicing regions whose boundaries depend on overlapping markers.
- Detect truncation early: compare actual vs expected record size.
When it happens
Trigger: Any code path where a byte slice with len(data)%2 != 0 reaches decodeUTF16LE — in practice, when the marker-delimited region extracted by ReadStringFromUTF16Binary contains an odd number of bytes (truncation, overlapping markers, or stray bytes inside the region).
Common situations: Truncated downloads or files cut off mid-record; a region slice off by one because start/end markers overlap; binary corruption from editing a UTF-16 file with an ASCII editor; concatenating files with an extra stray byte.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- error decoding UTF-16LE content: %w
- file is not in UTF-16LE format: %s
- end marker not found after start index %d: %s
- unrecognized theme assets kind. only "root", "folder", "colo
- error reading file %s: %w
AI-assisted analysis of spicetify/cli@1f13f73616 (2026-08-31).
Data as JSON: /api/errors/b099ae1d9d048448.
Report an issue: GitHub.