file_vcs_status TypeError with pygit2 on Python 3.14: bad argument type for built-in operation
Author: oandoniuCreated Apr 21, 2026Updated Apr 21, 2026
Description
When opening a file from a git repository while the current working directory is outside the repo, the file_vcs_status segment throws a TypeError.
Environment
- OS: Arch Linux
- Python: 3.14
- Powerline: 2.8.4 (Arch package)
- pygit2: 1.19.2
- Vim: 9.x with Python3 support
Error
vim /home/user/work/myrepo/./src/file.cpp
2026-04-21 09:03:37,605:ERROR:vim:file_vcs_status:Exception while computing segment: bad argument type for built-in operation
Traceback (most recent call last):
File "/usr/lib/python3.14/site-packages/powerline/segment.py", line 173, in process_segment
contents = segment['contents_func'](pl, segment_info)
File "/usr/lib/python3.14/site-packages/powerline/segment.py", line 412, in <lambda>
contents_func = lambda pl, segment_info: _contents_func(pl=pl, segment_info=segment_info, **args)
File "/usr/lib/python3.14/site-packages/powerline/segments/vim/__init__.py", line 570, in file_vcs_status
status = repo.status(os.path.relpath(name, repo.directory))
File "/usr/lib/python3.14/site-packages/powerline/lib/vcs/git.py", line 75, in status
return get_file_status(...)
File "/usr/lib/python3.14/site-packages/powerline/lib/vcs/__init__.py", line 131, in get_file_status
file_status_cache[keypath] = ans = get_func(directory, file_path)
File "/usr/lib/python3.14/site-packages/powerline/lib/vcs/git.py", line 115, in do_status
status = git.Repository(directory).status_file(path)
TypeError: bad argument type for built-in operationRoot Cause
In Python 3, buffer_name() in powerline/bindings/vim/__init__.py returns bytes (encoded buffer name):
def buffer_name(segment_info):
try:
name = segment_info['buffer'].name
except UnicodeDecodeError:
return vim_bufname(segment_info['bufnr'])
else:
return name.encode(segment_info['encoding']) if name else NoneThis bytes value is then passed to os.path.relpath() which returns bytes, and eventually reaches pygit2.Repository.status_file() which doesn't accept bytes - only strings.
Proposed Fix
In powerline/segments/vim/__init__.py, decode the buffer name before passing to os.path.relpath():
@requires_filesystem_watcher
@requires_segment_info
def file_vcs_status(pl, segment_info, create_watcher):
name = buffer_name(segment_info)
skip = not (name and (not vim_getbufoption(segment_info, 'buftype')))
if not skip:
repo = guess(path=name, create_watcher=create_watcher)
if repo is not None:
# Decode bytes to string for os.path.relpath and pygit2 compatibility
name_str = name.decode() if isinstance(name, bytes) else name
status = repo.status(os.path.relpath(name_str, repo.directory))
# ... rest of functionRelated Issues
- #2106 - Similar issue but on Windows with different error ("a bytes-like object is required, not 'str'")
- #1876 - Similar bytes/str mismatch issue from 2018
- #2222 - PR for related bytes decoding issue in
generate_directories()
The underlying issue is that buffer_name() returns bytes in Python 3, but many downstream functions expect strings.
Source: powerline/powerline