#define _GNU_SOURCE /* for getline */
 #endif
 #include <stdio.h>
+#include <sysexits.h>
 
 #include "compat.h"
 
        str[strlen(str)-1] = '\0';
 }
 
+/* Exit status code indicating temporary failure; user is invited to
+ * retry.
+ *
+ * For example, file(s) in the mail store were removed or renamed
+ * after notmuch new scanned the directories but before indexing the
+ * file(s). If the file was renamed, the indexing might not be
+ * complete, and the user is advised to re-run notmuch new.
+ */
+#define NOTMUCH_EXIT_TEMPFAIL EX_TEMPFAIL
+
 /* Exit status code indicating the requested format version is too old
  * (support for that version has been dropped).  CLI code should use
  * notmuch_exit_if_unsupported_format rather than directly exiting
 
     int total_files;
     int processed_files;
     int added_messages, removed_messages, renamed_messages;
+    int vanished_files;
     struct timeval tv_start;
 
     _filename_list_t *removed_files;
     case NOTMUCH_STATUS_FILE_NOT_EMAIL:
        fprintf (stderr, "Note: Ignoring non-mail file: %s\n", filename);
        break;
-    /* Fatal issues. Don't process anymore. */
     case NOTMUCH_STATUS_FILE_ERROR:
+       /* Someone renamed/removed the file between scandir and now. */
+       state->vanished_files++;
        fprintf (stderr, "Unexpected error with file %s\n", filename);
        (void) print_status_database ("add_file", notmuch, status);
-       goto DONE;
+       break;
+    /* Fatal issues. Don't process anymore. */
     case NOTMUCH_STATUS_READ_ONLY_DATABASE:
     case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
     case NOTMUCH_STATUS_OUT_OF_MEMORY:
     if (!no_hooks && !ret && !interrupted)
        ret = notmuch_run_hook (db_path, "post-new");
 
-    return ret || interrupted ? EXIT_FAILURE : EXIT_SUCCESS;
+    if (ret || interrupted)
+       return EXIT_FAILURE;
+
+    if (add_files_state.vanished_files)
+       return NOTMUCH_EXIT_TEMPFAIL;
+
+    return EXIT_SUCCESS;
 }