Index: uspace/app/nav/dlg/ioerrdlg.c
===================================================================
--- uspace/app/nav/dlg/ioerrdlg.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
+++ uspace/app/nav/dlg/ioerrdlg.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2025 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nav
+ * @{
+ */
+/**
+ * @file I/O Error Dialog
+ */
+
+#include <errno.h>
+#include <fmgt.h>
+#include <mem.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <ui/fixed.h>
+#include <ui/label.h>
+#include <ui/pbutton.h>
+#include <ui/resource.h>
+#include <ui/ui.h>
+#include <ui/window.h>
+#include "ioerrdlg.h"
+
+static void io_err_dlg_wnd_close(ui_window_t *, void *);
+static void io_err_dlg_wnd_kbd(ui_window_t *, void *, kbd_event_t *);
+
+ui_window_cb_t io_err_dlg_wnd_cb = {
+	.close = io_err_dlg_wnd_close,
+	.kbd = io_err_dlg_wnd_kbd
+};
+
+static void io_err_dlg_babort_clicked(ui_pbutton_t *, void *);
+static void io_err_dlg_bretry_clicked(ui_pbutton_t *, void *);
+
+ui_pbutton_cb_t io_err_dlg_babort_cb = {
+	.clicked = io_err_dlg_babort_clicked
+};
+
+ui_pbutton_cb_t io_err_dlg_bretry_cb = {
+	.clicked = io_err_dlg_bretry_clicked
+};
+
+/** Initialize I/O error dialog parameters structure.
+ *
+ * I/O error parameters structure must always be initialized using
+ * this function first.
+ *
+ * @param params I/O error dialog parameters structure
+ */
+void io_err_dlg_params_init(io_err_dlg_params_t *params)
+{
+	memset(params, 0, sizeof(io_err_dlg_params_t));
+	params->text1 = "";
+	params->text2 = "";
+}
+
+/** Create I/O error dialog.
+ *
+ * @param ui User interface
+ * @param params Dialog parameters
+ * @param rdialog Place to store pointer to new dialog
+ * @return EOK on success or an error code
+ */
+errno_t io_err_dlg_create(ui_t *ui, io_err_dlg_params_t *params,
+    io_err_dlg_t **rdialog)
+{
+	errno_t rc;
+	io_err_dlg_t *dialog;
+	ui_window_t *window = NULL;
+	ui_wnd_params_t wparams;
+	ui_fixed_t *fixed = NULL;
+	ui_label_t *label = NULL;
+	ui_pbutton_t *babort = NULL;
+	ui_pbutton_t *bretry = NULL;
+	gfx_rect_t rect;
+	ui_resource_t *ui_res;
+	char *name = NULL;
+
+	dialog = calloc(1, sizeof(io_err_dlg_t));
+	if (dialog == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	ui_wnd_params_init(&wparams);
+	wparams.caption = "I/O Error";
+
+	/* FIXME: Auto layout */
+	if (ui_is_textmode(ui)) {
+		wparams.rect.p0.x = 0;
+		wparams.rect.p0.y = 0;
+		wparams.rect.p1.x = 60;
+		wparams.rect.p1.y = 9;
+	} else {
+		wparams.rect.p0.x = 0;
+		wparams.rect.p0.y = 0;
+		wparams.rect.p1.x = 300;
+		wparams.rect.p1.y = 155;
+	}
+
+	rc = ui_window_create(ui, &wparams, &window);
+	if (rc != EOK)
+		goto error;
+
+	ui_window_set_cb(window, &io_err_dlg_wnd_cb, dialog);
+
+	ui_res = ui_window_get_res(window);
+
+	rc = ui_fixed_create(&fixed);
+	if (rc != EOK)
+		goto error;
+
+	rc = ui_label_create(ui_res, params->text1, &label);
+	if (rc != EOK)
+		goto error;
+
+	/* FIXME: Auto layout */
+	if (ui_is_textmode(ui)) {
+		rect.p0.x = 3;
+		rect.p0.y = 2;
+		rect.p1.x = 57;
+		rect.p1.y = 3;
+	} else {
+		rect.p0.x = 10;
+		rect.p0.y = 35;
+		rect.p1.x = 190;
+		rect.p1.y = 50;
+	}
+
+	ui_label_set_rect(label, &rect);
+	ui_label_set_halign(label, gfx_halign_center);
+
+	rc = ui_fixed_add(fixed, ui_label_ctl(label));
+	if (rc != EOK)
+		goto error;
+
+	label = NULL;
+
+	rc = ui_label_create(ui_res, params->text2, &label);
+	if (rc != EOK)
+		goto error;
+
+	/* FIXME: Auto layout */
+	if (ui_is_textmode(ui)) {
+		rect.p0.x = 3;
+		rect.p0.y = 4;
+		rect.p1.x = 57;
+		rect.p1.y = 5;
+	} else {
+		rect.p0.x = 10;
+		rect.p0.y = 35;
+		rect.p1.x = 190;
+		rect.p1.y = 50;
+	}
+
+	ui_label_set_rect(label, &rect);
+	ui_label_set_halign(label, gfx_halign_center);
+
+	rc = ui_fixed_add(fixed, ui_label_ctl(label));
+	if (rc != EOK)
+		goto error;
+
+	rc = ui_pbutton_create(ui_res, "Abort", &babort);
+	if (rc != EOK)
+		goto error;
+
+	ui_pbutton_set_cb(babort, &io_err_dlg_babort_cb, dialog);
+
+	/* FIXME: Auto layout */
+	if (ui_is_textmode(ui)) {
+		rect.p0.x = 20;
+		rect.p0.y = 6;
+		rect.p1.x = 30;
+		rect.p1.y = 7;
+	} else {
+		rect.p0.x = 55;
+		rect.p0.y = 120;
+		rect.p1.x = 145;
+		rect.p1.y = 148;
+	}
+
+	ui_pbutton_set_rect(babort, &rect);
+
+	ui_pbutton_set_default(babort, true);
+
+	rc = ui_fixed_add(fixed, ui_pbutton_ctl(babort));
+	if (rc != EOK)
+		goto error;
+
+	dialog->babort = babort;
+	babort = NULL;
+
+	rc = ui_pbutton_create(ui_res, "Retry", &bretry);
+	if (rc != EOK)
+		goto error;
+
+	ui_pbutton_set_cb(bretry, &io_err_dlg_bretry_cb, dialog);
+
+	/* FIXME: Auto layout */
+	if (ui_is_textmode(ui)) {
+		rect.p0.x = 32;
+		rect.p0.y = 6;
+		rect.p1.x = 42;
+		rect.p1.y = 7;
+	} else {
+		rect.p0.x = 155;
+		rect.p0.y = 120;
+		rect.p1.x = 245;
+		rect.p1.y = 148;
+	}
+
+	ui_pbutton_set_rect(bretry, &rect);
+
+	rc = ui_fixed_add(fixed, ui_pbutton_ctl(bretry));
+	if (rc != EOK)
+		goto error;
+
+	dialog->bretry = bretry;
+	bretry = NULL;
+
+	ui_window_add(window, ui_fixed_ctl(fixed));
+	fixed = NULL;
+
+	rc = ui_window_paint(window);
+	if (rc != EOK)
+		goto error;
+
+	dialog->window = window;
+	*rdialog = dialog;
+	return EOK;
+error:
+	if (name != NULL)
+		free(name);
+	if (babort != NULL)
+		ui_pbutton_destroy(babort);
+	if (bretry != NULL)
+		ui_pbutton_destroy(bretry);
+	if (label != NULL)
+		ui_label_destroy(label);
+	if (fixed != NULL)
+		ui_fixed_destroy(fixed);
+	if (window != NULL)
+		ui_window_destroy(window);
+	if (dialog != NULL)
+		free(dialog);
+	return rc;
+}
+
+/** Destroy prompt dialog.
+ *
+ * @param dialog Prompt dialog or @c NULL
+ */
+void io_err_dlg_destroy(io_err_dlg_t *dialog)
+{
+	if (dialog == NULL)
+		return;
+
+	ui_window_destroy(dialog->window);
+	free(dialog);
+}
+
+/** Set mesage dialog callback.
+ *
+ * @param dialog Prompt dialog
+ * @param cb Prompt dialog callbacks
+ * @param arg Callback argument
+ */
+void io_err_dlg_set_cb(io_err_dlg_t *dialog, io_err_dlg_cb_t *cb,
+    void *arg)
+{
+	dialog->cb = cb;
+	dialog->arg = arg;
+}
+
+/** Prompt dialog window close handler.
+ *
+ * @param window Window
+ * @param arg Argument (io_err_dlg_t *)
+ */
+static void io_err_dlg_wnd_close(ui_window_t *window, void *arg)
+{
+	io_err_dlg_t *dialog = (io_err_dlg_t *) arg;
+
+	(void)window;
+	if (dialog->cb != NULL && dialog->cb->close != NULL) {
+		dialog->cb->close(dialog, dialog->arg);
+	}
+}
+
+/** Prompt dialog window keyboard event handler.
+ *
+ * @param window Window
+ * @param arg Argument (io_err_dlg_t *)
+ * @param event Keyboard event
+ */
+static void io_err_dlg_wnd_kbd(ui_window_t *window, void *arg,
+    kbd_event_t *event)
+{
+	io_err_dlg_t *dialog = (io_err_dlg_t *) arg;
+
+	if (event->type == KEY_PRESS &&
+	    (event->mods & (KM_CTRL | KM_SHIFT | KM_ALT)) == 0) {
+		if (event->key == KC_ENTER) {
+			/* Confirm */
+			if (dialog->cb != NULL && dialog->cb->babort != NULL) {
+				dialog->cb->babort(dialog, dialog->arg);
+				return;
+			}
+		} else if (event->key == KC_ESCAPE) {
+			/* Cancel */
+			if (dialog->cb != NULL && dialog->cb->bretry != NULL) {
+				dialog->cb->bretry(dialog, dialog->arg);
+				return;
+			}
+		}
+	}
+
+	ui_window_def_kbd(window, event);
+}
+
+/** Prompt dialog OK button click handler.
+ *
+ * @param pbutton Push button
+ * @param arg Argument (io_err_dlg_t *)
+ */
+static void io_err_dlg_babort_clicked(ui_pbutton_t *pbutton, void *arg)
+{
+	io_err_dlg_t *dialog = (io_err_dlg_t *) arg;
+
+	if (dialog->cb != NULL && dialog->cb->babort != NULL) {
+		dialog->cb->babort(dialog, dialog->arg);
+	}
+}
+
+/** Prompt dialog cancel button click handler.
+ *
+ * @param pbutton Push button
+ * @param arg Argument (io_err_dlg_t *)
+ */
+static void io_err_dlg_bretry_clicked(ui_pbutton_t *pbutton, void *arg)
+{
+	io_err_dlg_t *dialog = (io_err_dlg_t *) arg;
+
+	(void)pbutton;
+	if (dialog->cb != NULL && dialog->cb->bretry != NULL) {
+		dialog->cb->bretry(dialog, dialog->arg);
+	}
+}
+
+/** @}
+ */
Index: uspace/app/nav/dlg/ioerrdlg.h
===================================================================
--- uspace/app/nav/dlg/ioerrdlg.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
+++ uspace/app/nav/dlg/ioerrdlg.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nav
+ * @{
+ */
+/**
+ * @file I/O Error Dialog
+ */
+
+#ifndef DLG_IOERRDLG_H
+#define DLG_IOERRDLG_H
+
+#include <errno.h>
+#include <types/ui/ui.h>
+#include "../types/dlg/ioerrdlg.h"
+
+extern void io_err_dlg_params_init(io_err_dlg_params_t *);
+extern errno_t io_err_dlg_create(ui_t *, io_err_dlg_params_t *,
+    io_err_dlg_t **);
+extern void io_err_dlg_set_cb(io_err_dlg_t *, io_err_dlg_cb_t *,
+    void *);
+extern void io_err_dlg_destroy(io_err_dlg_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/nav/dlg/newfiledlg.c
===================================================================
--- uspace/app/nav/dlg/newfiledlg.c	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/dlg/newfiledlg.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -352,7 +352,7 @@
 }
 
-/** Destroy prompt dialog.
- *
- * @param dialog Prompt dialog or @c NULL
+/** Destroy new file dialog.
+ *
+ * @param dialog New file dialog or @c NULL
  */
 void new_file_dlg_destroy(new_file_dlg_t *dialog)
@@ -365,8 +365,8 @@
 }
 
-/** Set mesage dialog callback.
- *
- * @param dialog Prompt dialog
- * @param cb Prompt dialog callbacks
+/** Set new file dialog callback.
+ *
+ * @param dialog new file dialog
+ * @param cb New file dialog callbacks
  * @param arg Callback argument
  */
@@ -378,5 +378,5 @@
 }
 
-/** Prompt dialog window close handler.
+/** New file dialog window close handler.
  *
  * @param window Window
@@ -393,5 +393,5 @@
 }
 
-/** Prompt dialog window keyboard event handler.
+/** New file dialog window keyboard event handler.
  *
  * @param window Window
@@ -432,5 +432,5 @@
 }
 
-/** Prompt dialog OK button click handler.
+/** New file dialog OK button click handler.
  *
  * @param pbutton Push button
@@ -452,5 +452,5 @@
 }
 
-/** Prompt dialog cancel button click handler.
+/** New file dialog cancel button click handler.
  *
  * @param pbutton Push button
Index: uspace/app/nav/meson.build
===================================================================
--- uspace/app/nav/meson.build	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/meson.build	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -29,4 +29,5 @@
 deps = [ 'fmgt', 'ui' ]
 src = files(
+	'dlg/ioerrdlg.c',
 	'dlg/newfiledlg.c',
 	'dlg/progress.c',
@@ -39,4 +40,5 @@
 
 test_src = files(
+	'dlg/ioerrdlg.c',
 	'dlg/newfiledlg.c',
 	'dlg/progress.c',
Index: uspace/app/nav/nav.c
===================================================================
--- uspace/app/nav/nav.c	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/nav.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -36,8 +36,10 @@
 
 #include <fibril.h>
+#include <fmgt.h>
 #include <gfx/coord.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <task.h>
 #include <ui/fixed.h>
@@ -46,4 +48,5 @@
 #include <ui/ui.h>
 #include <ui/window.h>
+#include "dlg/ioerrdlg.h"
 #include "menu.h"
 #include "newfile.h"
@@ -87,4 +90,14 @@
 	.babort = navigator_progress_babort,
 	.close = navigator_progress_close
+};
+
+static void navigator_io_err_abort(io_err_dlg_t *, void *);
+static void navigator_io_err_retry(io_err_dlg_t *, void *);
+static void navigator_io_err_close(io_err_dlg_t *, void *);
+
+static io_err_dlg_cb_t navigator_io_err_dlg_cb = {
+	.babort = navigator_io_err_abort,
+	.bretry = navigator_io_err_retry,
+	.close = navigator_io_err_close
 };
 
@@ -244,4 +257,8 @@
 	}
 
+	fibril_mutex_initialize(&navigator->io_err_act_lock);
+	fibril_condvar_initialize(&navigator->io_err_act_cv);
+	navigator->io_err_act_sel = false;
+
 	*rnavigator = navigator;
 	return EOK;
@@ -630,4 +647,111 @@
 }
 
+/** Called by fmgt to query for I/O error recovery action.
+ *
+ * @param arg Argument (navigator_t *)
+ * @param err I/O error report
+ * @return Recovery action to take.
+ */
+fmgt_error_action_t navigator_io_error_query(void *arg, fmgt_io_error_t *err)
+{
+	navigator_t *nav = (navigator_t *)arg;
+	io_err_dlg_t *dlg;
+	io_err_dlg_params_t params;
+	fmgt_error_action_t err_act;
+	char *text1;
+	errno_t rc;
+	int rv;
+
+	io_err_dlg_params_init(&params);
+	rv = asprintf(&text1, err->optype == fmgt_io_write ?
+	    "Error writing file %s." : "Error reading file %s.",
+	    err->fname);
+	if (rv < 0)
+		return fmgt_er_abort;
+
+	params.text1 = text1;
+	params.text2 = str_error(err->rc);
+
+	ui_lock(nav->ui);
+	rc = io_err_dlg_create(nav->ui, &params, &dlg);
+	if (rc != EOK) {
+		ui_unlock(nav->ui);
+		free(text1);
+		return fmgt_er_abort;
+	}
+
+	io_err_dlg_set_cb(dlg, &navigator_io_err_dlg_cb, (void *)nav);
+
+	ui_unlock(nav->ui);
+	free(text1);
+
+	fibril_mutex_lock(&nav->io_err_act_lock);
+
+	while (!nav->io_err_act_sel) {
+		fibril_condvar_wait(&nav->io_err_act_cv,
+		    &nav->io_err_act_lock);
+	}
+
+	err_act = nav->io_err_act;
+	nav->io_err_act_sel = false;
+	fibril_mutex_unlock(&nav->io_err_act_lock);
+
+	return err_act;
+}
+
+/** I/O error dialog abort button was pressed.
+ *
+ * @param dlg I/O error dialog
+ * @param arg Argument (navigator_t *)
+ */
+static void navigator_io_err_abort(io_err_dlg_t *dlg, void *arg)
+{
+	navigator_t *nav = (navigator_t *)arg;
+
+	io_err_dlg_destroy(dlg);
+
+	fibril_mutex_lock(&nav->io_err_act_lock);
+	nav->io_err_act = fmgt_er_abort;
+	nav->io_err_act_sel = true;
+	fibril_condvar_signal(&nav->io_err_act_cv);
+	fibril_mutex_unlock(&nav->io_err_act_lock);
+}
+
+/** I/O error dialog retry button was pressed.
+ *
+ * @param dlg I/O error dialog
+ * @param arg Argument (navigator_t *)
+ */
+static void navigator_io_err_retry(io_err_dlg_t *dlg, void *arg)
+{
+	navigator_t *nav = (navigator_t *)arg;
+
+	io_err_dlg_destroy(dlg);
+
+	fibril_mutex_lock(&nav->io_err_act_lock);
+	nav->io_err_act = fmgt_er_retry;
+	nav->io_err_act_sel = true;
+	fibril_condvar_signal(&nav->io_err_act_cv);
+	fibril_mutex_unlock(&nav->io_err_act_lock);
+}
+
+/** I/O error dialog closure requested.
+ *
+ * @param dlg I/O error dialog
+ * @param arg Argument (navigator_t *)
+ */
+static void navigator_io_err_close(io_err_dlg_t *dlg, void *arg)
+{
+	navigator_t *nav = (navigator_t *)arg;
+
+	io_err_dlg_destroy(dlg);
+
+	fibril_mutex_lock(&nav->io_err_act_lock);
+	nav->io_err_act = fmgt_er_abort;
+	nav->io_err_act_sel = true;
+	fibril_condvar_signal(&nav->io_err_act_cv);
+	fibril_mutex_unlock(&nav->io_err_act_lock);
+}
+
 /** @}
  */
Index: uspace/app/nav/nav.h
===================================================================
--- uspace/app/nav/nav.h	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/nav.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -38,4 +38,5 @@
 
 #include <errno.h>
+#include <fmgt.h>
 #include "types/dlg/progress.h"
 #include "types/nav.h"
@@ -52,4 +53,5 @@
 extern errno_t navigator_worker_start(navigator_t *, void (*)(void *),
     void *);
+extern fmgt_error_action_t navigator_io_error_query(void *, fmgt_io_error_t *);
 
 #endif
Index: uspace/app/nav/newfile.c
===================================================================
--- uspace/app/nav/newfile.c	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/newfile.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -69,4 +69,5 @@
 static fmgt_cb_t new_file_fmgt_cb = {
 	.abort_query = new_file_abort_query,
+	.io_error_query = navigator_io_error_query,
 	.progress = new_file_progress,
 };
Index: uspace/app/nav/types/dlg/ioerrdlg.h
===================================================================
--- uspace/app/nav/types/dlg/ioerrdlg.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
+++ uspace/app/nav/types/dlg/ioerrdlg.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2025 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nav
+ * @{
+ */
+/**
+ * @file I/O Error Dialog
+ */
+
+#ifndef TYPES_DLG_IOERRDLG_H
+#define TYPES_DLG_IOERRDLG_H
+
+#include <errno.h>
+#include <io/kbd_event.h>
+#include <io/pos_event.h>
+#include <ui/entry.h>
+#include <ui/pbutton.h>
+#include <ui/window.h>
+
+struct io_err_dlg;
+typedef struct io_err_dlg io_err_dlg_t;
+
+enum {
+	/** Maximum number of buttons in I/O error dialog. */
+	io_err_dlg_maxbtn = 2
+};
+
+/** Which choices the user can select from. */
+typedef enum {
+	/** Abort, Retry */
+	iedc_abort_retry
+} io_err_dlg_choice_t;
+
+/** I/O error dialog parameters */
+typedef struct {
+	/** First line of text */
+	const char *text1;
+	/** Second line of text */
+	const char *text2;
+	/** The choice that the user is given */
+	io_err_dlg_choice_t choice;
+} io_err_dlg_params_t;
+
+/** I/O error dialog callback */
+typedef struct io_err_dlg_cb {
+	/** Abort button was pressed */
+	void (*babort)(io_err_dlg_t *, void *);
+	/** Retry button was pressed */
+	void (*bretry)(io_err_dlg_t *, void *);
+	/** Window closure requested (e.g. via close button) */
+	void (*close)(io_err_dlg_t *, void *);
+} io_err_dlg_cb_t;
+
+/** I/O error dialog */
+typedef struct io_err_dlg {
+	/** Dialog window */
+	ui_window_t *window;
+	/** Abort button */
+	ui_pbutton_t *babort;
+	/** Retry button */
+	ui_pbutton_t *bretry;
+	/** New file dialog callbacks */
+	io_err_dlg_cb_t *cb;
+	/** Callback argument */
+	void *arg;
+} io_err_dlg_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/app/nav/types/nav.h
===================================================================
--- uspace/app/nav/types/nav.h	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/nav/types/nav.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -38,4 +38,5 @@
 
 #include <fibril.h>
+#include <fmgt.h>
 #include <stdbool.h>
 #include <ui/fixed.h>
@@ -65,4 +66,13 @@
 	/** Abort current file management operation */
 	bool abort_op;
+
+	/** @c true if user selected I/O error recovery action */
+	bool io_err_act_sel;
+	/** Selected I/O error recovery action */
+	fmgt_error_action_t io_err_act;
+	/** Signalled when user selects I/O error recovery action */
+	fibril_condvar_t io_err_act_cv;
+	/** Synchronizes access to I/O error recovery action */
+	fibril_mutex_t io_err_act_lock;
 } navigator_t;
 
Index: uspace/app/newfile/newfile.c
===================================================================
--- uspace/app/newfile/newfile.c	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/app/newfile/newfile.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -49,6 +49,8 @@
 static bool newfile_abort_query(void *);
 static void newfile_progress(void *, fmgt_progress_t *);
+static fmgt_error_action_t newfile_io_error_query(void *, fmgt_io_error_t *);
 
 static bool prog_upd = false;
+static bool nonint = false;
 static bool quiet = false;
 
@@ -57,5 +59,6 @@
 static fmgt_cb_t newfile_fmgt_cb = {
 	.abort_query = newfile_abort_query,
-	.progress = newfile_progress
+	.io_error_query = newfile_io_error_query,
+	.progress = newfile_progress,
 };
 
@@ -121,4 +124,61 @@
 }
 
+/** Called by fmgt to let user choose I/O error recovery action.
+ *
+ * @param arg Argument (not used)
+ * @param err I/O error report
+ * @return Error recovery action.
+ */
+static fmgt_error_action_t newfile_io_error_query(void *arg,
+    fmgt_io_error_t *err)
+{
+	cons_event_t event;
+	kbd_event_t *ev;
+	errno_t rc;
+
+	(void)arg;
+
+	if (nonint)
+		return fmgt_er_abort;
+
+	if (prog_upd)
+		putchar('\n');
+
+	fprintf(stderr, "I/O error %s file '%s' (%s).\n",
+	    err->optype == fmgt_io_write ? "writing" : "reading",
+	    err->fname, str_error(err->rc));
+	fprintf(stderr, "[A]bort or [R]etry?\n");
+
+	if (con == NULL)
+		return fmgt_er_abort;
+
+	while (true) {
+		rc = console_get_event(con, &event);
+		if (rc != EOK)
+			return fmgt_er_abort;
+
+		if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS) {
+			ev = &event.ev.key;
+			if ((ev->mods & KM_ALT) == 0 &&
+			    (ev->mods & KM_CTRL) == 0) {
+				if (ev->c == 'r' || ev->c == 'R')
+					return fmgt_er_retry;
+				if (ev->c == 'a' || ev->c == 'A')
+					return fmgt_er_abort;
+			}
+		}
+
+		if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS) {
+			ev = &event.ev.key;
+			if ((ev->mods & KM_ALT) == 0 &&
+			    (ev->mods & KM_SHIFT) == 0 &&
+			    (ev->mods & KM_CTRL) != 0) {
+				if (ev->key == KC_C)
+					return fmgt_er_abort;
+			}
+		}
+	}
+}
+
 int main(int argc, char *argv[])
 {
@@ -126,5 +186,4 @@
 	errno_t rc;
 	int i;
-	bool nonint = false;
 	bool sparse = false;
 	char *fsize = NULL;
@@ -210,5 +269,5 @@
 	rc = fmgt_new_file(fmgt, fname, nbytes, sparse ? nf_sparse : nf_none);
 	if (prog_upd)
-		printf("\n");
+		putchar('\n');
 	if (rc != EOK) {
 		printf("Error creating file: %s.\n", str_error(rc));
Index: uspace/lib/fmgt/include/types/fmgt.h
===================================================================
--- uspace/lib/fmgt/include/types/fmgt.h	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/lib/fmgt/include/types/fmgt.h	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -39,4 +39,5 @@
 
 #include <capa.h>
+#include <errno.h>
 #include <fibril_synch.h>
 #include <stdbool.h>
@@ -52,7 +53,34 @@
 } fmgt_progress_t;
 
+/** File management I/O operation type */
+typedef enum {
+	/** Read */
+	fmgt_io_read,
+	/** Write */
+	fmgt_io_write
+} fmgt_io_op_type_t;
+
+/** File management I/O error report */
+typedef struct {
+	/** File name */
+	const char *fname;
+	/** Operation type */
+	fmgt_io_op_type_t optype;
+	/** Error code */
+	errno_t rc;
+} fmgt_io_error_t;
+
+/** File management I/O error recovery action */
+typedef enum {
+	/** Retry */
+	fmgt_er_retry,
+	/** Abort */
+	fmgt_er_abort
+} fmgt_error_action_t;
+
 /** File management callbacks */
 typedef struct {
 	bool (*abort_query)(void *);
+	fmgt_error_action_t (*io_error_query)(void *, fmgt_io_error_t *);
 	void (*progress)(void *, fmgt_progress_t *);
 } fmgt_cb_t;
Index: uspace/lib/fmgt/src/fmgt.c
===================================================================
--- uspace/lib/fmgt/src/fmgt.c	(revision 856a7b49196de7975e942a76a1d3e3c579774b4d)
+++ uspace/lib/fmgt/src/fmgt.c	(revision bb4d0b520c39e20a5f604e8fbd4e96fa93516fc0)
@@ -221,4 +221,13 @@
 }
 
+/** Stop progress update timer.
+ *
+ * @param fmgt File management object
+ */
+static void fmgt_timer_stop(fmgt_t *fmgt)
+{
+	(void)fibril_timer_clear(fmgt->timer);
+}
+
 /** Query caller whether operation should be aborted.
  *
@@ -232,4 +241,19 @@
 	else
 		return false;
+}
+
+/** Query caller how to recover from I/O error.
+ *
+ * @param fmgt File management object
+ * @param err I/O error report
+ * @return What error recovery action should be taken.
+ */
+static fmgt_error_action_t fmgt_io_error_query(fmgt_t *fmgt,
+    fmgt_io_error_t *err)
+{
+	if (fmgt->cb != NULL && fmgt->cb->io_error_query != NULL)
+		return fmgt->cb->io_error_query(fmgt->cb_arg, err);
+	else
+		return fmgt_er_abort;
 }
 
@@ -250,4 +274,6 @@
 	uint64_t now;
 	char *buffer;
+	fmgt_io_error_t err;
+	fmgt_error_action_t action;
 	errno_t rc;
 
@@ -270,4 +296,5 @@
 	fmgt_initial_progress_update(fmgt);
 
+	/* Create sparse file? */
 	if ((flags & nf_sparse) != 0) {
 		fmgt->curf_procb = fsize - 1;
@@ -280,5 +307,19 @@
 			now = BUFFER_SIZE;
 
-		rc = vfs_write(fd, &pos, buffer, now, &nw);
+		do {
+			rc = vfs_write(fd, &pos, buffer, now, &nw);
+			if (rc == EOK)
+				break;
+
+			/* I/O error */
+			err.fname = fname;
+			err.optype = fmgt_io_write;
+			err.rc = rc;
+			fmgt_timer_stop(fmgt);
+			action = fmgt_io_error_query(fmgt, &err);
+			fmgt_timer_start(fmgt);
+		} while (action == fmgt_er_retry);
+
+		/* Not recovered? */
 		if (rc != EOK) {
 			free(buffer);
