maotoumao/MusicFree · warning
panel.imageViewer.saveImageFail
panel.imageViewer.saveImageFail
Error message
panel.imageViewer.saveImageFail
What it means
In the image viewer panel (src/components/panels/types/imageViewer.tsx), saving an image resolves with a resultPath on success; on rejection the catch logs the error and toasts t('panel.imageViewer.saveImageFail', {reason}). The message 'panel.imageViewer.saveImageFail' is an untranslated i18n key, shown when the translation is missing or t receives only the key, with the underlying native save failure as the reason.
Source
Thrown at src/components/panels/types/imageViewer.tsx:59
}
}
source={{
uri: url,
}}
/>
<Button
text={t("panel.imageViewer.saveImage")}
type="primary"
style={styles.button}
onPress={() => {
saveToGallery(url)
.then((resultPath) => {
Toast.success(t("panel.imageViewer.saveImageSuccess", {
path: resultPath,
}));
}).catch(e => {
errorLog("Save failed", e?.message ?? e);
Toast.warn(t("panel.imageViewer.saveImageFail", {
reason: e?.message ?? e,
}));
});
}}
/>
</PanelFullscreen>
);
}
const styles = StyleSheet.create({
container: {
justifyContent: "center",
alignItems: "center",
gap: rpx(48),
},
button: {
marginHorizontal: rpx(24),
paddingHorizontal: rpx(200),
View on GitHub (pinned to d118b18b3d)
Solutions
- Grant storage/photos permission to the app, then retry the save.
- Check 'Save failed' in the error log for the real reason (network vs permission vs path) and address it.
- Add the panel.imageViewer.saveImageFail/Success keys to all locale files so users see the actual reason.
- Verify the image URL is reachable (open it in a browser) and retry.
Defensive patterns
Strategy: try-catch
Validate before calling
const reachable = await fetch(imageUrl, { method: 'HEAD' }).then(r => r.ok).catch(() => false);
if (!reachable) { Toast.warn('image unavailable'); return; }
const hasPerm = await checkStoragePermission();
if (!hasPerm) await requestStoragePermission(); Try / catch
saveImage(imageUrl)
.then(path => Toast.success(t('panel.imageViewer.saveImageSuccess', { path })))
.catch(e => {
errorLog('Save failed', e?.message ?? e);
Toast.warn(t('panel.imageViewer.saveImageFail', { reason: e?.message ?? e }));
}); Prevention
- Ensure the panel.imageViewer.* i18n keys exist in every locale file.
- Request storage permission lazily right before the first save.
- Check image URL validity/expiry before offering save.
- Log the underlying error (already done via errorLog) to distinguish network vs permission causes.
When it happens
Trigger: Tapping save in the image viewer when the native save (download to gallery / file write) rejects: no storage permission, invalid source URL, network failure fetching the image, or the destination path being unwritable.
Common situations: Android storage permission not granted; image URL expired or blocked by the source site; saving on a device with full storage; i18n resource missing the panel.imageViewer.* keys so the raw key appears in the toast.
Related errors
- 状态栏歌词开启失败,请到手机系统设置打开悬浮窗权限
- toast.resumeFail
- 安装失败: ${res.message}
- dialog.markdownDialog.openExternalLink
- panel.addToMusicSheet.toast.fail
AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30).
Data as JSON: /api/errors/01c46b61f2fbf73b.
Report an issue: GitHub.