spicetify/cli · error

end marker not found after start index %d: %s

Error message

end marker not found after start index %d: %s

What it means

ReadStringFromUTF16Binary locates a delimited string inside a UTF-16LE file (e.g. Spotify prefs) by searching for an encoded start marker, then an encoded end marker after it. This error is returned when the start marker was found but bytes.Index never matches the UTF-16LE-encoded end marker in the remaining content. It wraps the end marker text in the message so the caller can see which delimiter was missing.

Source

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

	var searchStartMarker, searchEndMarker []byte

	if !isUTF16LE {
		return "", -1, -1, fmt.Errorf("file is not in UTF-16LE format: %s", inputFile)
	}

	contentToSearch = fileContent[2:]
	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)))

View on GitHub (pinned to 1f13f73616)

Solutions

  1. Verify the end marker string matches exactly what the producing application writes (including case and spacing) and re-run.
  2. Open the file in a UTF-16LE-aware hex/text editor and confirm the closing marker bytes actually exist after the start marker.
  3. Check the reported start index in the error message and inspect bytes from there onward to see what text actually follows.
  4. Regenerate or re-export the file if it is truncated/corrupt, then retry the parse.

Example fix

// before: marker literal guess
s, a, b, err := utils.ReadStringFromUTF16Binary(prefs, []byte("<name>"), []byte("</Value>"))
// after: marker verified against the actual file content
s, a, b, err := utils.ReadStringFromUTF16Binary(prefs, []byte("<name>"), []byte("</name>"))
if err != nil {
	log.Fatalf("parse prefs: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check the file exists and is plausibly UTF-16LE before calling
if fi, err := os.Stat(inputFile); err != nil || fi.Size() < 4 {
	return fmt.Errorf("prefs file missing or too small")
}

Type guard

// Go has no runtime type guards; use an explicit error sentinel check
func isEndMarkerNotFound(err error) bool {
	return err != nil && strings.Contains(err.Error(), "end marker not found")
}

Try / catch

val, _, _, err := utils.ReadStringFromUTF16Binary(prefs, start, end)
if err != nil {
	if strings.Contains(err.Error(), "end marker not found") {
		// fall back to defaults or re-export the file
		return defaultVal, nil
	}
	return fmt.Errorf("parse prefs: %w", err)
}

Prevention

When it happens

Trigger: Calling ReadStringFromUTF16Binary(inputFile, startMarker, endMarker) where the file contains the startMarker (UTF-16LE encoded) but no endMarker after it — e.g. a typo'd end marker, a marker in a different case/format than the file's encoding, or a truncated/corrupt file that lost the closing section.

Common situations: Parsing an older or newer version of the file whose delimiter strings changed; passing an ASCII end marker while the file stores UTF-16 (handled internally, but a wrong literal still fails); the file was cut off mid-write so the closing tag is absent; marker text differs by whitespace or capitalization from what the app wrote.

Related errors


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