HKUDS/nanobot · error · TuiUnavailableError
TUI release file failed verification
Error message
TUI release file failed verification: {name} What it means
In _verified_release_archive, a bundle file's SHA-256 does not match the digest declared in MANIFEST.sha256. Integrity verification failed for the named file after successful parsing, so the whole bundle is rejected rather than installed; the input at fault is the named archive member.
Solutions
- Retry the download to rule out transfer corruption
- Re-publish the release if the uploaded file genuinely differs from the manifest digest
- Treat persistent failures as tampering and investigate the distribution channel
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at nanobot/cli/tui_launcher.py:355 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of HKUDS/nanobot@42f37dc4c0 (2026-08-26).
Data as JSON: /api/errors/9280f511a22a1844.
Report an issue: GitHub.
Appendix: source
Thrown at nanobot/cli/tui_launcher.py:355
raise TuiUnavailableError("TUI release archive contains invalid entries")
if set(names) != expected_names:
raise TuiUnavailableError("TUI release archive is incomplete")
for entry in entries:
limit = 150 * 1024 * 1024 if entry.filename == asset else _TUI_RELEASE_LIMITS[
entry.filename
]
if entry.file_size == 0 or entry.file_size > limit:
raise TuiUnavailableError(
f"TUI release file has an invalid size: {entry.filename}"
)
files[entry.filename] = archive.read(entry)
except zipfile.BadZipFile as exc:
raise TuiUnavailableError("downloaded TUI archive is not a valid ZIP file") from exc
checksums = _release_manifest(files["MANIFEST.sha256"], asset)
for name, expected in checksums.items():
if hashlib.sha256(files[name]).hexdigest() != expected:
raise TuiUnavailableError(f"TUI release file failed verification: {name}")
return files
def _cached_release_tui(target_dir: Path, asset: str) -> Path | None:
target = target_dir / asset
manifest = target_dir / "MANIFEST.sha256"
if not target.is_file() and not manifest.exists():
return None
try:
checksums = _release_manifest(manifest.read_bytes(), asset)
for name, expected in checksums.items():
if hashlib.sha256((target_dir / name).read_bytes()).hexdigest() != expected:
raise OSError("cached release checksum mismatch")
if os.name != "nt":
target.chmod(0o755)
except (OSError, TuiUnavailableError):
_clear_cached_release(target_dir, asset)
return NoneView on GitHub (pinned to 42f37dc4c0)