--- a/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc +++ b/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc @@ -1838,13 +1838,27 @@ unsigned int updates = 0; for (iter = mset.begin(); iter != mset.end(); ++iter) { - Xapian::Document doc = iter.get_document(); try { + /* get_document() belongs inside the try: it is the + * call that throws DocNotFoundError when a document + * has no termlist, and this rebuild exists precisely + * to salvage databases the native compact refused. */ + Xapian::Document doc = iter.get_document(); xdb->dbw->replace_document(doc.get_docid(), doc); if (++updates > FLATCURVE_MANUAL_OPTIMIZE_COMMIT_LIMIT) { xdb->dbw->commit(); updates = 0; } + } catch (Xapian::DocNotFoundError &e) { + /* A document listed in the MSet whose termlist is + * gone. It belongs to a message that no longer + * exists, so there is nothing to carry over -- skip + * it rather than abort, which would leave every shard + * in place to accumulate without bound. */ + e_debug(backend->event, "Optimize: skipping " + "unreadable document; %s", + e.get_description().c_str()); + continue; } catch (Xapian::Error &e) { *error_r = t_strdup(e.get_description().c_str()); return -1;