maotoumao/MusicFree · warning
panel.associateLrc.targetExpired
Error message
panel.associateLrc.targetExpired
What it means
When associating a lyric, the panel parses a unique key from the clipboard/input and looks it up in mediaCache. If no cached media entry exists for that key, the target media has 'expired' from cache, so association is aborted: a warning toast is shown and a sentinel Error('CLIPBOARD TIMEOUT') is thrown to signal the specific failure (so the generic fail toast at line 66 is suppressed).
Source
Thrown at src/components/panels/types/associateLrc.tsx:51
height={vmax(30)}
renderBody={() => (
<>
<PanelHeader
title={t("panel.associateLrc.title")}
onCancel={hidePanel}
onOk={async () => {
const inputValue =
input ?? (await Clipboard.getString());
if (inputValue) {
try {
const targetMedia = parseMediaUniqueKey(
inputValue.trim(),
);
// 目标也要写进去
const targetCache =
mediaCache.getMediaCache(targetMedia);
if (!targetCache) {
Toast.warn(
t("panel.associateLrc.targetExpired"),
);
// TODO: ERROR CODE
throw new Error("CLIPBOARD TIMEOUT");
}
lyricManager.associateLyric(musicItem, {
...targetMedia,
...targetCache,
});
Toast.success(t("panel.associateLrc.toast.success"));
hidePanel();
} catch (e: any) {
if (e.message !== "CLIPBOARD TIMEOUT") {
Toast.warn(t("panel.associateLrc.toast.fail"));
}
errorLog("关联歌词失败", e?.message);
}View on GitHub (pinned to d118b18b3d)
Solutions
- Re-open the source media (play/search it) so mediaCache re-caches the entry, then retry the association.
- Paste the full media info instead of relying on a stale unique key from the clipboard.
- Type the key into the input field rather than falling back to Clipboard.getString() to avoid stale clipboard content.
- Developer: extend mediaCache TTL or persist cache entries across restarts.
Example fix
// before
const targetCache = mediaCache.getMediaCache(targetMedia);
if (!targetCache) {
Toast.warn(t("panel.associateLrc.targetExpired"));
throw new Error("CLIPBOARD TIMEOUT");
}
// after
const targetCache = mediaCache.getMediaCache(targetMedia);
if (!targetCache) {
const refreshed = await mediaCache.addMusicToCache(targetMedia); // rehydrate
if (!refreshed) {
Toast.warn(t("panel.associateLrc.targetExpired"));
throw new Error("CLIPBOARD TIMEOUT");
}
} Defensive patterns
Strategy: validation
Validate before calling
const targetMedia = parseMediaUniqueKey(inputValue.trim());
const targetCache = targetMedia ? mediaCache.getMediaCache(targetMedia) : undefined;
if (!targetCache) {
// re-open/re-play the target media first, or abort before associating
return;
} Type guard
function hasCachedMedia(key: unknown): key is IMedia.MediaUniqueKey {
return typeof key === 'string' && mediaCache.getMediaCache(parseMediaUniqueKey(key)) != null;
} Try / catch
try {
// association logic
} catch (e: any) {
if (e?.message === "CLIPBOARD TIMEOUT") {
// cache-miss path already toasted; do not double-toast
} else {
Toast.warn(t("panel.associateLrc.toast.fail"));
}
} Prevention
- Re-open the target media before associating so its cache entry exists.
- Avoid depending on stale clipboard content from previous app sessions.
- Clear the clipboard fallback when the input field has content.
- Extend mediaCache retention if associations happen long after playback.
When it happens
Trigger: onOk in AssociateLrc (associateLrc.tsx:39-75) runs parseMediaUniqueKey(inputValue.trim()) and mediaCache.getMediaCache(targetMedia) returns undefined — i.e. the clipboard contains a media unique key whose cached entry was evicted or never existed (cache cleared, app restarted, or clipboard text is not a valid cached key).
Common situations: User copies a media key, clears app data/cache or restarts the app, then tries to associate lyrics; pasting arbitrary text that parses as a key but has no cache entry; mediaCache eviction after long sessions.
Related errors
- panel.associateLrc.toast.fail
- panel.musicItemLyricOptions.settingFail
- panel.imageViewer.saveImageFail
- 安装失败: ${res.message}
- panel.musicItemLyricOptions.desktopLyricPermissionError
AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30).
Data as JSON: /api/errors/acda795e58887a58.
Report an issue: GitHub.