{
        struct bch_fs *c = trans->c;
        struct printbuf buf = PRINTBUF;
+       struct btree_iter iter2 = {};
        int ret = PTR_ERR_OR_ZERO(i);
        if (ret)
                return ret;
 
        bool have_inode = i && !i->whiteout;
 
-       if (!have_inode && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) {
-               ret =   reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?:
-                       bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
-               if (ret)
-                       goto err;
+       if (!have_inode && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes)))
+               goto reconstruct;
 
-               inode->last_pos.inode--;
-               ret = bch_err_throw(c, transaction_restart_nested);
-               goto err;
+       if (have_inode && btree_matches_i_mode(iter->btree_id, i->inode.bi_mode))
+               goto out;
+
+       prt_printf(&buf, ", ");
+
+       bool have_old_inode = false;
+       darray_for_each(inode->inodes, i2)
+               if (!i2->whiteout &&
+                   bch2_snapshot_is_ancestor(c, k.k->p.snapshot, i2->inode.bi_snapshot) &&
+                   btree_matches_i_mode(iter->btree_id, i2->inode.bi_mode)) {
+                       prt_printf(&buf, "but found good inode in older snapshot\n");
+                       bch2_inode_unpacked_to_text(&buf, &i2->inode);
+                       prt_newline(&buf);
+                       have_old_inode = true;
+                       break;
+               }
+
+       struct bkey_s_c k2;
+       unsigned nr_keys = 0;
+
+       prt_printf(&buf, "found keys:\n");
+
+       for_each_btree_key_max_norestart(trans, iter2, iter->btree_id,
+                                        SPOS(k.k->p.inode, 0, k.k->p.snapshot),
+                                        POS(k.k->p.inode, U64_MAX),
+                                        0, k2, ret) {
+               nr_keys++;
+               if (nr_keys <= 10) {
+                       bch2_bkey_val_to_text(&buf, c, k2);
+                       prt_newline(&buf);
+               }
+               if (nr_keys >= 100)
+                       break;
        }
 
-       if (fsck_err_on(!have_inode,
-                       trans, key_in_missing_inode,
-                       "key in missing inode:\n%s",
-                       (printbuf_reset(&buf),
-                        bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
-               goto delete;
+       if (ret)
+               goto err;
 
-       if (fsck_err_on(have_inode && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode),
-                       trans, key_in_wrong_inode_type,
-                       "key for wrong inode mode %o:\n%s",
-                       i->inode.bi_mode,
-                       (printbuf_reset(&buf),
-                        bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
-               goto delete;
+       if (nr_keys > 100)
+               prt_printf(&buf, "found > %u keys for this missing inode\n", nr_keys);
+       else if (nr_keys > 10)
+               prt_printf(&buf, "found %u keys for this missing inode\n", nr_keys);
+
+       if (!have_inode) {
+               if (fsck_err_on(!have_inode,
+                               trans, key_in_missing_inode,
+                               "key in missing inode%s", buf.buf)) {
+                       /*
+                        * Maybe a deletion that raced with data move, or something
+                        * weird like that? But if we know the inode was deleted, or
+                        * it's just a few keys, we can safely delete them.
+                        *
+                        * If it's many keys, we should probably recreate the inode
+                        */
+                       if (have_old_inode || nr_keys <= 2)
+                               goto delete;
+                       else
+                               goto reconstruct;
+               }
+       } else {
+               /*
+                * not autofix, this one would be a giant wtf - bit error in the
+                * inode corrupting i_mode?
+                *
+                * may want to try repairing inode instead of deleting
+                */
+               if (fsck_err_on(!btree_matches_i_mode(iter->btree_id, i->inode.bi_mode),
+                               trans, key_in_wrong_inode_type,
+                               "key for wrong inode mode %o%s",
+                               i->inode.bi_mode, buf.buf))
+                       goto delete;
+       }
 out:
 err:
 fsck_err:
+       bch2_trans_iter_exit(trans, &iter2);
        printbuf_exit(&buf);
        bch_err_fn(c, ret);
        return ret;
 delete:
+       /*
+        * XXX: print out more info
+        * count up extents for this inode, check if we have different inode in
+        * an older snapshot version, perhaps decide if we want to reconstitute
+        */
        ret = bch2_btree_delete_at(trans, iter, BTREE_UPDATE_internal_snapshot_node);
        goto out;
+reconstruct:
+       ret =   reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?:
+               bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
+       if (ret)
+               goto err;
+
+       inode->last_pos.inode--;
+       ret = bch_err_throw(c, transaction_restart_nested);
+       goto out;
 }
 
 static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_walker *w)