# Buggy code
def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None):
    """Retrieve information about the Vault and clean the data

    When data is saved, it has a header prepended and is formatted into 80
    character lines.  This method extracts the information from the header
    and then removes the header and the inserted newlines.  The string returned
    is suitable for processing by the Cipher classes.

    :arg b_vaulttext: byte str containing the data from a save file
    :returns: a byte str suitable for passing to a Cipher class's
        decrypt() function.
    """
    # used by decrypt
    default_vault_id = default_vault_id or C.DEFAULT_VAULT_IDENTITY

    b_tmpdata = b_vaulttext_envelope.split(b"\n")
    b_tmpheader = b_tmpdata[0].strip().split(b";")

    b_version = b_tmpheader[1].strip()
    cipher_name = to_text(b_tmpheader[2].strip())
    vault_id = default_vault_id
    # vault_id = None

    # Only attempt to find vault_id if the vault file is version 1.2 or newer
    # if self.b_version == b'1.2':
    if len(b_tmpheader) >= 4:
        vault_id = to_text(b_tmpheader[3].strip())

    b_ciphertext = b"".join(b_tmpdata[1:])

    return b_ciphertext, b_version, cipher_name, vault_id


# Traceback (TypeError)
ansible-vault edit group_vars/role/vault.yml --vault-password-file=vault_pass -vvv
Using /etc/ansible/ansible.cfg as config file
[DEPRECATION WARNING]: ansible.utils.unicode.to_unicode is deprecated.  Use ansible.module_utils._text.to_text instead.
This feature will be removed
in version 2.4. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ERROR! Unexpected Exception: Odd-length string
the full traceback was:

Traceback (most recent call last):
File "/usr/bin/ansible-vault", line 85, in <module>
sys.exit(cli.run())
File "/home/user/.local/lib/python2.7/site-packages/ansible/cli/vault.py", line 122, in run
self.execute()
File "/home/user/.local/lib/python2.7/site-packages/ansible/cli/__init__.py", line 145, in execute
fn()
File "/home/user/.local/lib/python2.7/site-packages/ansible/cli/vault.py", line 158, in execute_edit
self.editor.edit_file(f)
File "/home/user/.local/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py", line 456, in edit_file
plaintext = self.vault.decrypt(ciphertext)
File "/home/user/.local/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py", line 259, in decrypt
b_plaintext = this_cipher.decrypt(b_vaulttext, self.b_password)
File "/home/user/.local/lib/python2.7/site-packages/ansible/parsing/vault/__init__.py", line 743, in decrypt
b_vaulttext = unhexlify(b_vaulttext)
TypeError: Odd-length string

# Fixed code
def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None):
    """Retrieve information about the Vault and clean the data

    When data is saved, it has a header prepended and is formatted into 80
    character lines.  This method extracts the information from the header
    and then removes the header and the inserted newlines.  The string returned
    is suitable for processing by the Cipher classes.

    :arg b_vaulttext: byte str containing the data from a save file
    :returns: a byte str suitable for passing to a Cipher class's
        decrypt() function.
    """
    # used by decrypt
    default_vault_id = default_vault_id or C.DEFAULT_VAULT_IDENTITY

    b_tmpdata = b_vaulttext_envelope.splitlines()
    b_tmpheader = b_tmpdata[0].strip().split(b";")

    b_version = b_tmpheader[1].strip()
    cipher_name = to_text(b_tmpheader[2].strip())
    vault_id = default_vault_id
    # vault_id = None

    # Only attempt to find vault_id if the vault file is version 1.2 or newer
    # if self.b_version == b'1.2':
    if len(b_tmpheader) >= 4:
        vault_id = to_text(b_tmpheader[3].strip())

    b_ciphertext = b"".join(b_tmpdata[1:])

    return b_ciphertext, b_version, cipher_name, vault_id