Index: src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 14766)
+++ src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(working copy)
@@ -85,6 +85,8 @@
     private final SideButton fixButton;
     /** The ignore button */
     private final SideButton ignoreButton;
+    /** The reset ignorelist button */
+    private final SideButton ignorelistManagement;
     /** The select button */
     private final SideButton selectButton;
     /** The lookup button */
@@ -174,9 +176,32 @@
             });
             ignoreButton.setEnabled(false);
             buttons.add(ignoreButton);
+
+            if (!ValidatorPrefHelper.PREF_IGNORELIST_KEEP_BACKUP.get()) {
+                // Clear the backup ignore list
+                Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP, null);
+            }
+            ignorelistManagement = new SideButton(new AbstractAction() {
+                {
+                    putValue(NAME, tr("Manage Ignore"));
+                    putValue(SHORT_DESCRIPTION, tr("Manage the ignore list"));
+                    new ImageProvider("dialogs", "fix").getResource().attachImageIcon(this, true);
+                }
+
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    IgnoreListManagementDialog dialog = new IgnoreListManagementDialog();
+                    if (dialog.getValue() == 1) {
+                        // TODO save
+                    }
+                }
+            });
+            buttons.add(ignorelistManagement);
         } else {
             ignoreButton = null;
+            ignorelistManagement = null;
         }
+
         createLayout(tree, true, buttons);
     }
 
@@ -287,7 +312,6 @@
     /**
      * Sets the selection of the map to the current selected items.
      */
-    @SuppressWarnings("unchecked")
     private void setSelectedItems() {
         DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
         if (tree == null || ds == null)
Index: src/org/openstreetmap/josm/gui/dialogs/IgnoreListManagementDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/IgnoreListManagementDialog.java	(nonexistent)
+++ src/org/openstreetmap/josm/gui/dialogs/IgnoreListManagementDialog.java	(working copy)
@@ -0,0 +1,194 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.swing.ImageIcon;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import org.openstreetmap.josm.actions.ValidateAction;
+import org.openstreetmap.josm.data.validation.OsmValidator;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+
+/**
+ * A management window for the validator's ignorelist
+ * @author Taylor Smock
+ * @since xxx
+ */
+public class IgnoreListManagementDialog extends ExtendedDialog {
+    enum BUTTONS {
+        OK(0, tr("OK"), new ImageProvider("ok")),
+        CLEAR(1, tr("Clear"), new ImageProvider("dialogs", "fix")),
+        RESTORE(2, tr("Restore"), new ImageProvider("dialogs", "copy")),
+        CANCEL(3, tr("Cancel"), new ImageProvider("cancel"));
+
+        private int index;
+        private String name;
+        private ImageIcon icon;
+
+        BUTTONS(int index, String name, ImageProvider image) {
+            this.index = index;
+            this.name = name;
+            this.icon = image.getResource().getImageIcon();
+        }
+
+        public ImageIcon getImageIcon() {
+            return icon;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    private static final String TITLE = tr("Ignore List Management");
+
+    private static final String[] BUTTON_TEXTS = {BUTTONS.OK.getName(), BUTTONS.CLEAR.getName(),
+            BUTTONS.RESTORE.getName(), BUTTONS.CANCEL.getName()
+    };
+
+    private static final ImageIcon[] BUTTON_IMAGES = {BUTTONS.OK.getImageIcon(), BUTTONS.CLEAR.getImageIcon(),
+            BUTTONS.RESTORE.getImageIcon(), BUTTONS.CANCEL.getImageIcon()
+    };
+
+    private final JPanel panel = new JPanel(new GridBagLayout());
+
+    private final JTextArea ignoreErrors;
+
+    private String initialText;
+
+    /**
+     * Create a new {@link IgnoreListManagementDialog}
+     */
+    public IgnoreListManagementDialog() {
+        super(MainApplication.getMainFrame(), TITLE, BUTTON_TEXTS, false);
+        setButtonIcons(BUTTON_IMAGES);
+
+        ignoreErrors = buildIgnoreErrorList();
+        JScrollPane scroll = GuiHelper.embedInVerticalScrollPane(ignoreErrors);
+
+        panel.add(scroll, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER));
+        setContent(panel);
+        setDefaultButton(1);
+        setupDialog();
+        showDialog();
+    }
+
+    @Override
+    public void buttonAction(int buttonIndex, ActionEvent evt) {
+        // Currently OK/Cancel buttons do nothing
+        if (buttonIndex == BUTTONS.RESTORE.getIndex()) {
+            dispose();
+            final int answer = rerunValidatorPrompt();
+            if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) {
+                OsmValidator.restoreErrorList();
+            }
+        } else if (buttonIndex == BUTTONS.CLEAR.getIndex()) {
+            dispose();
+            final int answer = rerunValidatorPrompt();
+            if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) {
+                OsmValidator.resetErrorList();
+            }
+        } else if (buttonIndex == BUTTONS.OK.getIndex()) {
+            dispose();
+            String text = ignoreErrors.getText();
+            if (!initialText.equals(text)) {
+                String[] textArray = text.split(System.lineSeparator());
+                Logging.debug(initialText);
+                Logging.debug(text);
+                final int answer = rerunValidatorPrompt();
+                if (answer == JOptionPane.YES_OPTION || answer == JOptionPane.NO_OPTION) {
+                    HashMap<String, String> map = new HashMap<>();
+                    map.putAll(OsmValidator.getIgnoredErrors());
+                    OsmValidator.resetErrorList();
+                    for (String line : textArray) {
+                        if (line.equals("/* " + tr("There are no ignored errors") + " */")) continue;
+                        String[] lineparts = line.split(" /\\* ");
+                        if (lineparts.length == 1) {
+                            OsmValidator.addIgnoredError(lineparts[0]);
+                        } else if (lineparts.length == 2) {
+                            OsmValidator.addIgnoredError(lineparts[0], lineparts[1].replace(" */", ""));
+                        }
+                    }
+                }
+            }
+        } else {
+            super.buttonAction(buttonIndex, evt);
+        }
+    }
+
+    /**
+     * Build a JTextArea with the ignorelist
+     * @return ignorelist as a JTextArea
+     */
+    public JTextArea buildIgnoreErrorList() {
+        String displayText = "";
+        HashMap<String, String> map = OsmValidator.getIgnoredErrors();
+        if (map.isEmpty()) {
+            OsmValidator.initialize();
+            map = OsmValidator.getIgnoredErrors();
+        }
+        for (String key : map.keySet()) {
+            String ignore = key;
+            if (map.get(key) != null && !map.get(key).isBlank()) {
+                ignore += " /* " + map.get(key) + " */";
+            }
+            ignore += System.lineSeparator();
+            Logging.debug(ignore);
+            displayText += ignore;
+        }
+        JTextArea text = new JTextArea();
+        if (displayText.isBlank()) {
+            displayText = "/* " + tr("There are no ignored errors") + " */";
+        }
+        text.setText(displayText);
+        initialText = displayText;
+        return text;
+    }
+
+    /**
+     * Prompt to rerun the validator when the ignore list changes
+     * @return {@code JOptionPane.YES_OPTION}, {@code JOptionPane.NO_OPTION},
+     *  or {@code JOptionPane.CANCEL_OPTION}
+     */
+    public int rerunValidatorPrompt() {
+        MapFrame map = MainApplication.getMap();
+        List<TestError> errors = map.validatorDialog.tree.getErrors();
+        ValidateAction validateAction = ValidatorDialog.validateAction;
+        if (!validateAction.isEnabled() || errors == null || errors.isEmpty()) return JOptionPane.NO_OPTION;
+        final int answer = ConditionalOptionPaneUtil.showOptionDialog(
+                "rerun_validation_when_ignorelist_changed",
+                MainApplication.getMainFrame(),
+                "<hmtl><h3>" + tr("Should the validation be rerun?") + "</h3></html>",
+                tr("Ignored error filter changed"),
+                JOptionPane.YES_NO_CANCEL_OPTION,
+                JOptionPane.QUESTION_MESSAGE,
+                null,
+                null);
+        if (answer == JOptionPane.YES_OPTION) {
+            validateAction.doValidate(true);
+        }
+        return answer;
+    }
+}
Index: src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 14766)
+++ src/org/openstreetmap/josm/data/validation/OsmValidator.java	(working copy)
@@ -7,7 +7,6 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -88,8 +87,7 @@
     /** Grid detail, multiplier of east,north values for valuable cell sizing */
     private static double griddetail;
 
-    private static final Collection<String> ignoredErrors = new TreeSet<>();
-
+    private static final HashMap<String, String> ignoredErrors = new HashMap<>();
     /**
      * All registered tests
      */
@@ -204,11 +202,21 @@
     private static void loadIgnoredErrors() {
         ignoredErrors.clear();
         if (ValidatorPrefHelper.PREF_USE_IGNORE.get()) {
+            Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST).forEach(map -> {
+                ignoredErrors.putAll(map);
+            });
             Path path = Paths.get(getValidatorDir()).resolve("ignorederrors");
             try {
                 if (path.toFile().exists()) {
                     try {
-                        ignoredErrors.addAll(Files.readAllLines(path, StandardCharsets.UTF_8));
+                        TreeSet<String> treeSet = new TreeSet<>();
+                        treeSet.addAll(Files.readAllLines(path, StandardCharsets.UTF_8));
+                        treeSet.forEach(ignore -> {
+                            ignoredErrors.putIfAbsent(ignore, "");
+                        });
+
+                        saveIgnoredErrors();
+                        Files.deleteIfExists(path);
                     } catch (FileNotFoundException e) {
                         Logging.debug(Logging.getErrorMessage(e));
                     } catch (IOException e) {
@@ -228,29 +236,79 @@
      * @see TestError#getIgnoreSubGroup()
      */
     public static void addIgnoredError(String s) {
-        ignoredErrors.add(s);
+        addIgnoredError(s, "");
     }
 
     /**
+     * Adds an ignored error
+     * @param s The ignore group / sub group name
+     * @param description What the error actually is
+     * @see TestError#getIgnoreGroup()
+     * @see TestError#getIgnoreSubGroup()
+     */
+    public static void addIgnoredError(String s, String description) {
+        ignoredErrors.put(s, description);
+    }
+
+    /**
      * Check if a error should be ignored
      * @param s The ignore group / sub group name
      * @return <code>true</code> to ignore that error
      */
     public static boolean hasIgnoredError(String s) {
-        return ignoredErrors.contains(s);
+        return ignoredErrors.containsKey(s);
     }
 
     /**
-     * Saves the names of the ignored errors to a file
+     * Get the list of all ignored errors
+     * @return The <code>Collection&ltString&gt</code> of errors that are ignored
      */
+    public static HashMap<String, String> getIgnoredErrors() {
+        return ignoredErrors;
+    }
+
+    /**
+     * Reset the error list by deleting ignorederrors
+     */
+    public static void resetErrorList() {
+        saveIgnoredErrors();
+        backupErrorList();
+        Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null);
+        OsmValidator.initialize();
+    }
+
+    /**
+     * Restore the error list by copying ignorederrors.bak to ignorederrors
+     */
+    public static void restoreErrorList() {
+        saveIgnoredErrors();
+        List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP);
+        backupErrorList();
+        Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, tlist);
+        OsmValidator.initialize();
+    }
+
+    private static void backupErrorList() {
+        List<Map<String, String>> tlist = Config.getPref().getListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, null);
+        Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST_BACKUP, tlist);
+    }
+
+    /**
+     * Saves the names of the ignored errors to a preference
+     */
     public static void saveIgnoredErrors() {
-        try (PrintWriter out = new PrintWriter(new File(getValidatorDir(), "ignorederrors"), StandardCharsets.UTF_8.name())) {
-            for (String e : ignoredErrors) {
-                out.println(e);
+        List<Map<String, String>> list = new ArrayList<>();
+        list.add(ignoredErrors);
+        int i = 0;
+        while (i < list.size()) {
+            if (list.get(i) == null || list.get(i).isEmpty()) {
+                list.remove(i);
+                continue;
             }
-        } catch (IOException e) {
-            Logging.error(e);
+            i++;
         }
+        if (list.isEmpty()) list = null;
+        Config.getPref().putListOfMaps(ValidatorPrefHelper.PREF_IGNORELIST, list);
     }
 
     /**
Index: src/org/openstreetmap/josm/data/preferences/sources/ValidatorPrefHelper.java
===================================================================
--- src/org/openstreetmap/josm/data/preferences/sources/ValidatorPrefHelper.java	(revision 14766)
+++ src/org/openstreetmap/josm/data/preferences/sources/ValidatorPrefHelper.java	(working copy)
@@ -44,6 +44,15 @@
     /** The preferences for ignored severity other */
     public static final BooleanProperty PREF_OTHER = new BooleanProperty(PREFIX + ".other", false);
 
+    /** The preferences key for the ignorelist */
+    public static final String PREF_IGNORELIST = PREFIX + ".ignorelist";
+
+    /** The preferences key for the ignorelist backup */
+    public static final String PREF_IGNORELIST_BACKUP = PREFIX + ".ignorelist.bak";
+
+    /** The preferences key for whether or not the ignorelist backup should be cleared on start */
+    public static final BooleanProperty PREF_IGNORELIST_KEEP_BACKUP = new BooleanProperty(PREFIX + ".ignorelist.bak.keep", false);
+
     /**
      * The preferences key for enabling the permanent filtering
      * of the displayed errors in the tree regarding the current selection
@@ -50,9 +59,6 @@
      */
     public static final String PREF_FILTER_BY_SELECTION = PREFIX + ".selectionFilter";
 
-    /**
-     * Constructs a new {@code PresetPrefHelper}.
-     */
     public ValidatorPrefHelper() {
         super(MapCSSTagChecker.ENTRIES_PREF_KEY, SourceType.TAGCHECKER_RULE);
     }
