# Buggy code
def rekey_file(self, filename, new_vault_secret, new_vault_id=None):
    # follow the symlink
    filename = self._real_path(filename)

    prev = os.stat(filename)
    b_vaulttext = self.read_data(filename)
    vaulttext = to_text(b_vaulttext)

    display.vvvvv(
        'Rekeying file "%s" to with new vault-id "%s" and vault secret %s'
        % (filename, new_vault_id, new_vault_secret)
    )
    try:
        plaintext, vault_id_used, _dummy = self.vault.decrypt_and_get_vault_id(
            vaulttext
        )
    except AnsibleError as e:
        raise AnsibleError("%s for %s" % (to_bytes(e), to_bytes(filename)))

    # This is more or less an assert, see #18247
    if new_vault_secret is None:
        raise AnsibleError(
            "The value for the new_password to rekey %s with is not valid" % filename
        )

    # FIXME: VaultContext...?  could rekey to a different vault_id in the same VaultSecrets

    # Need a new VaultLib because the new vault data can be a different
    # vault lib format or cipher (for ex, when we migrate 1.0 style vault data to
    # 1.1 style data we change the version and the cipher). This is where a VaultContext might help

    # the new vault will only be used for encrypting, so it doesn't need the vault secrets
    # (we will pass one in directly to encrypt)
    new_vault = VaultLib(secrets={})
    b_new_vaulttext = new_vault.encrypt(
        plaintext, new_vault_secret, vault_id=new_vault_id
    )

    self.write_data(b_new_vaulttext, filename)

    # preserve permissions
    os.chmod(filename, prev.st_mode)
    os.chown(filename, prev.st_uid, prev.st_gid)

    display.vvvvv(
        'Rekeyed file "%s" (decrypted with vault id "%s") was encrypted with new vault-id "%s" and vault secret %s'
        % (filename, vault_id_used, new_vault_id, new_vault_secret)
    )


# Traceback (OSError)
ansible-vault 2.6.3
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/the-noob/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible-vault
python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
Using /etc/ansible/ansible.cfg as config file
Vault password:
ERROR! Unexpected Exception, this is probably a bug: [Errno 2] No such file or directory
the full traceback was:

Traceback (most recent call last):
File "/usr/bin/ansible-vault", line 118, in <module>
exit_code = cli.run()
File "/usr/lib/python2.7/dist-packages/ansible/cli/vault.py", line 255, in run
self.execute()
File "/usr/lib/python2.7/dist-packages/ansible/cli/__init__.py", line 155, in execute
fn()
File "/usr/lib/python2.7/dist-packages/ansible/cli/vault.py", line 446, in execute_edit
self.editor.edit_file(f)
File "/usr/lib/python2.7/dist-packages/ansible/parsing/vault/__init__.py", line 975, in edit_file
force_save=False, vault_id=vault_id)
File "/usr/lib/python2.7/dist-packages/ansible/parsing/vault/__init__.py", line 864, in _edit_file_helper
subprocess.call(self._editor_shell_command(tmp_path))
File "/usr/lib/python2.7/subprocess.py", line 523, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

# Fixed code
def rekey_file(self, filename, new_vault_secret, new_vault_id=None):
    # follow the symlink
    filename = self._real_path(filename)

    prev = os.stat(filename)
    b_vaulttext = self.read_data(filename)
    vaulttext = to_text(b_vaulttext)

    display.vvvvv(
        'Rekeying file "%s" to with new vault-id "%s" and vault secret %s'
        % (filename, new_vault_id, new_vault_secret)
    )
    try:
        plaintext, vault_id_used, _dummy = self.vault.decrypt_and_get_vault_id(
            vaulttext
        )
    except AnsibleError as e:
        raise AnsibleError("%s for %s" % (to_native(e), to_native(filename)))

    # This is more or less an assert, see #18247
    if new_vault_secret is None:
        raise AnsibleError(
            "The value for the new_password to rekey %s with is not valid" % filename
        )

    # FIXME: VaultContext...?  could rekey to a different vault_id in the same VaultSecrets

    # Need a new VaultLib because the new vault data can be a different
    # vault lib format or cipher (for ex, when we migrate 1.0 style vault data to
    # 1.1 style data we change the version and the cipher). This is where a VaultContext might help

    # the new vault will only be used for encrypting, so it doesn't need the vault secrets
    # (we will pass one in directly to encrypt)
    new_vault = VaultLib(secrets={})
    b_new_vaulttext = new_vault.encrypt(
        plaintext, new_vault_secret, vault_id=new_vault_id
    )

    self.write_data(b_new_vaulttext, filename)

    # preserve permissions
    os.chmod(filename, prev.st_mode)
    os.chown(filename, prev.st_uid, prev.st_gid)

    display.vvvvv(
        'Rekeyed file "%s" (decrypted with vault id "%s") was encrypted with new vault-id "%s" and vault secret %s'
        % (filename, vault_id_used, new_vault_id, new_vault_secret)
    )