spicetify/cli · error

error decoding UTF-16LE content: %w

Error message

error decoding UTF-16LE content: %w

What it means

After slicing out the marker-delimited region, ReadStringFromUTF16Binary passes those bytes to decodeUTF16LE to convert UTF-16LE to UTF-8. If decoding fails, the error is wrapped as "error decoding UTF-16LE content: %w". Currently the only underlying failure decodeUTF16LE produces is an odd-length byte slice, so this error almost always means the extracted region has an odd number of bytes.

Source

Thrown at src/utils/file-utils.go:53

	searchStartMarker = encodeUTF16LE(startMarker)
	searchEndMarker = encodeUTF16LE(endMarker)

	startIdx = bytes.Index(contentToSearch, searchStartMarker)
	if startIdx == -1 {
		return "", -1, -1, fmt.Errorf("start marker not found: %s", string(startMarker))
	}

	searchSpace := contentToSearch[startIdx+len(searchStartMarker):]
	endIdx = bytes.Index(searchSpace, searchEndMarker)
	if endIdx == -1 {
		return "", -1, -1, fmt.Errorf("end marker not found after start index %d: %s", startIdx+len(searchStartMarker), string(endMarker))
	}

	stringContentBytes := contentToSearch[startIdx : startIdx+len(searchStartMarker)+endIdx+len(searchEndMarker)]

	decodedStringBytes, err := decodeUTF16LE(stringContentBytes)
	if err != nil {
		return "", -1, -1, fmt.Errorf("error decoding UTF-16LE content: %w", err)
	}

	// Adjust indices to be byte offsets in the original file
	originalStartIdx := 2 + startIdx
	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
}

View on GitHub (pinned to 1f13f73616)

Solutions

  1. Inspect the bytes between the markers to confirm the region is a whole number of UTF-16 code units (even byte count).
  2. Check that start/end markers are distinct and non-overlapping so the slice boundary math is correct.
  3. Re-obtain the file from the application rather than using a hand-edited or partially converted copy.
  4. Unwrap the %w error to confirm it is the odd-length case, then validate the file's UTF-16LE integrity before parsing.

Example fix

// before: blind parse of a suspicious file
val, _, _, err := utils.ReadStringFromUTF16Binary(prefs, start, end)
// after: sanity-check file size is even after the 2-byte BOM first
if fi, _ := os.Stat(prefs); fi != nil && fi.Size()%2 != 0 {
	log.Fatal("prefs file has odd size; not valid UTF-16LE")
}
val, _, _, err := utils.ReadStringFromUTF16Binary(prefs, start, end)
Defensive patterns

Strategy: validation

Validate before calling

// Validate the region is decodable UTF-16 (even byte length) before/after extraction
func validUTF16Region(data []byte) bool { return len(data)%2 == 0 }

Type guard

// Go: narrow via error unwrap
func isDecodeErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "error decoding UTF-16LE content")
}

Try / catch

val, _, _, err := utils.ReadStringFromUTF16Binary(prefs, start, end)
if err != nil {
	var base error = err
	if errors.Unwrap(err) != nil { base = errors.Unwrap(err) }
	return fmt.Errorf("utf16 decode failed (%v); file may be corrupt", base)
}

Prevention

When it happens

Trigger: Calling ReadStringFromUTF16Binary when the bytes between (and including) the start and end markers have odd length. Note the slicing arithmetic at file-utils.go:49 uses endIdx relative to the search space combined with marker lengths, so overlapping/duplicated markers or a malformed region can produce an odd-length slice that fails UTF-16 decoding.

Common situations: A file edited by hand where the delimiters no longer pair up cleanly; start and end markers that overlap or occur an odd number of bytes apart; a file that was partially converted between encodings so the region contains stray single bytes; using markers that themselves contain multi-byte surrogate characters and mismatched pairs.

Related errors


AI-assisted analysis of spicetify/cli@1f13f73616 (2026-08-31). Data as JSON: /api/errors/a9e5e96821ae0d10. Report an issue: GitHub.