# Buggy code
def save(self, title=None, temporary=False):
    """Saves all changes to the configuration files.

    This function first checks for save errors, if none are found,
    all configuration changes made will be saved. According to the
    function parameters. If an exception is raised, a new checkpoint
    was not created.

    :param str title: The title of the save. If a title is given, the
        configuration will be saved as a new checkpoint and put in a
        timestamped directory.

    :param bool temporary: Indicates whether the changes made will
        be quickly reversed in the future (ie. challenges)

    :raises .errors.PluginError: If there was an error in Augeas, in
        an attempt to save the configuration, or an error creating a
        checkpoint

    """
    save_state = self.aug.get("/augeas/save")
    self.aug.set("/augeas/save", "noop")
    # Existing Errors
    ex_errs = self.aug.match("/augeas//error")
    try:
        # This is a noop save
        self.aug.save()
    except (RuntimeError, IOError):
        self._log_save_errors(ex_errs)
        # Erase Save Notes
        self.save_notes = ""
        raise errors.PluginError("Error saving files, check logs for more info.")

    # Retrieve list of modified files
    # Note: Noop saves can cause the file to be listed twice, I used a
    # set to remove this possibility. This is a known augeas 0.10 error.
    save_paths = self.aug.match("/augeas/events/saved")

    # If the augeas tree didn't change, no files were saved and a backup
    # should not be created
    save_files = set()
    if save_paths:
        for path in save_paths:
            save_files.add(self.aug.get(path)[6:])
        self.add_to_checkpoint(save_files, self.save_notes, temporary=temporary)

    self.aug.set("/augeas/save", save_state)
    self.save_notes = ""
    self.aug.save()

    # Force reload if files were modified
    # This is needed to recalculate augeas directive span
    if save_files:
        for sf in save_files:
            self.aug.remove("/files/" + sf)
        self.aug.load()
    if title and not temporary:
        self.finalize_checkpoint(title)


# Traceback (PluginError)
Cannot find a cert or key directive in /files/etc/apache2/sites-available/default-ssl.conf/IfModule/VirtualHost. VirtualHost was not modified
Encountered exception:
Traceback (most recent call last):
File "/home/bmw/src/certbot/certbot/client.py", line 439, in deploy_certificate
fullchain_path=fullchain_path)
File "/home/bmw/src/certbot/certbot-apache/certbot_apache/configurator.py", line 269, in deploy_cert
"Unable to find cert and/or key directives")
PluginError: Unable to find cert and/or key directives

Calling registered functions
Reporting to user: Unable to install the certificate
Exiting abnormally:
Traceback (most recent call last):
File "/usr/local/bin/certbot", line 11, in <module>
load_entry_point('certbot', 'console_scripts', 'certbot')()
File "/home/bmw/src/certbot/certbot/main.py", line 743, in main
return config.func(config, plugins)
File "/home/bmw/src/certbot/certbot/main.py", line 604, in run
_install_cert(config, le_client, domains, new_lineage)
File "/home/bmw/src/certbot/certbot/main.py", line 469, in _install_cert
path_provider.cert_path, path_provider.chain_path, path_provider.fullchain_path)
File "/home/bmw/src/certbot/certbot/client.py", line 439, in deploy_certificate
fullchain_path=fullchain_path)
File "/home/bmw/src/certbot/certbot-apache/certbot_apache/configurator.py", line 269, in deploy_cert
"Unable to find cert and/or key directives")
PluginError: Unable to find cert and/or key directives

# Fixed code
def save(self, title=None, temporary=False):
    """Saves all changes to the configuration files.

    This function first checks for save errors, if none are found,
    all configuration changes made will be saved. According to the
    function parameters. If an exception is raised, a new checkpoint
    was not created.

    :param str title: The title of the save. If a title is given, the
        configuration will be saved as a new checkpoint and put in a
        timestamped directory.

    :param bool temporary: Indicates whether the changes made will
        be quickly reversed in the future (ie. challenges)

    """
    save_files = self.unsaved_files()
    if save_files:
        self.add_to_checkpoint(save_files, self.save_notes, temporary=temporary)

    self.save_notes = ""
    self.aug.save()

    # Force reload if files were modified
    # This is needed to recalculate augeas directive span
    if save_files:
        for sf in save_files:
            self.aug.remove("/files/" + sf)
        self.aug.load()
    if title and not temporary:
        self.finalize_checkpoint(title)