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

  1. Grant storage/photos permission to the app, then retry the save.
  2. Check 'Save failed' in the error log for the real reason (network vs permission vs path) and address it.
  3. Add the panel.imageViewer.saveImageFail/Success keys to all locale files so users see the actual reason.
  4. 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

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


AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30). Data as JSON: /api/errors/01c46b61f2fbf73b. Report an issue: GitHub.