subframe7536/maple-font · error · Exception
Error reading file: {file_path} - {e}
Error message
Error reading file: {file_path} - {e} What it means
get_directory_hash walks a directory and hashes each file in 4KB chunks. If any file cannot be read due to an IOError/OSError (permission denied, file vanished mid-walk, too many open files, etc.), it wraps the OS error in this Exception with the file path. It is thrown so update_dir_hash / check_directory_hash callers get one consistent error type naming the offending file.
Source
Thrown at source/py/utils.py:278
return sha256.hexdigest(), zip_name_without_ext
def get_directory_hash(dir_path: str) -> str:
hasher = hashlib.sha256()
for root, _, files in sorted(walk(dir_path)):
for file in sorted(files):
file_path = path.join(root, file)
try:
with open(file_path, "rb") as f:
while True:
# 4KB chunk size
chunk = f.read(4096)
if not chunk:
break
hasher.update(chunk)
except (IOError, OSError) as e:
raise Exception(f"Error reading file: {file_path} - {e}")
return hasher.hexdigest()
def check_directory_hash(dir_path: str, hash_path: str | None = None) -> bool:
if not path.exists(dir_path):
print(f"{dir_path} not exist, skip computing hash")
return False
with open(hash_path or f"{dir_path}.sha256", "r") as f:
return f.readline() == get_directory_hash(dir_path)
def merge_ttfonts(
base_font_path: str, extra_font_path: str, use_pyftmerge: bool = False
) -> TTFont:
"""
Merge glyphs from ``source_font`` into ``base_font``, skipping duplicate glyph names.
View on GitHub (pinned to c08fda97fe)
Solutions
- Fix permissions on the reported file (chmod/chown) or rerun the command with sufficient privileges.
- Remove or exclude unreadable/special files (symlinks, sockets) from the hashed directory.
- Rerun the build if the file was transiently deleted; stop processes racing on the directory.
- Raise the open-file limit (ulimit -n) if the directory contains very many files.
Example fix
// before
# update_dir_hash('/build/output') # PermissionError wrapped
// after (shell)
# sudo chmod -R u+rw /build/output && python build.py Defensive patterns
Strategy: try-catch
Validate before calling
import os
def assert_dir_readable(dir_path):
for root, _, files in os.walk(dir_path):
for f in files:
p = os.path.join(root, f)
if not os.path.isfile(p) or os.path.islink(p):
continue
with open(p, "rb"):
pass # raises PermissionError before hashing starts Type guard
import os, stat
def is_readable_regular_file(path: str) -> bool:
try:
st = os.stat(path)
return stat.S_ISREG(st.st_mode) and os.access(path, os.R_OK)
except OSError:
return False Try / catch
try:
h = update_dir_hash(dir_path)
except Exception as e:
if str(e).startswith("Error reading file:"):
print("Fix permissions or remove unreadable file:", e)
raise Prevention
- Run builds as a user with read access to all build inputs/outputs.
- Exclude special files (sockets, fifos, broken symlinks) from hashed dirs.
- Avoid concurrent processes deleting files in the hashed directory.
- Raise ulimit -n when hashing directories with very many files.
When it happens
Trigger: Calling update_dir_hash(dir_path) or check_directory_hash(dir_path) when any file under dir_path cannot be opened for reading: unreadable permissions, a broken symlink, a file deleted between directory scan and read, or an unreadable special file.
Common situations: Running the build in a container/CI where the output dir contains root-owned files; antivirus or another process deleting files mid-hash; hashing a directory containing sockets/fifos; hitting the open-file limit with many files.
AI-assisted analysis of subframe7536/maple-font@c08fda97fe (2026-08-28).
Data as JSON: /api/errors/aaf39366c5e7c115.
Report an issue: GitHub.