Doppelvoice v0.3.2 — HOTFIX: onefile startup crash
🚨 Critical hotfix. v0.3.0 and v0.3.1 .exe binaries crashed at startup with TypeError: Cannot log to objects of type 'NoneType' for all users who double-clicked the bundled .exe. v0.3.2 is the fixed binary.
Download
Doppelvoice-v0.3.2-win64.zip (60.5 MB)
SHA256: 4DCCA817B5031CCE2DB95E287C35D1C2E5FE5923B9DB2295A66B6DB48569047F
If you're on v0.3.0 or v0.3.1: download this and replace your Doppelvoice.exe. Your .env in %APPDATA%\Doppelvoice\ is preserved.
Root cause
PyInstaller's onefile + windowed bootloader (console=False) detaches stdio. Inside a bundled GUI app sys.stderr is None, but utils/log.py was doing logger.add(sys.stderr, ...) unconditionally. loguru rejects None sinks with TypeError, killing the .exe on every double-click.
This regression slipped past me because in dev mode (python -m doppelvoice) sys.stderr is always a real TTY, so the bug never surfaced until a real user fired up the bundled binary.
Fixed
utils/log.py setup_logging: skip thesys.stderrconsole sink whensys.stderr is None. The file sink under%APPDATA%\Doppelvoice\logs\keeps working — users still get logs.utils/log.py _patcher: same fix for the redact-failure fallbacksys.stderr.write(...).__main__.py: explicitif stream is None: continuebefore stdio reconfigure for clarity.
Tests
Added test_setup_logging_with_none_stderr: monkeypatches sys.stderr = None and asserts setup_logging does not raise + the file sink still produces output. Total tests now 94.
Verified
Locally retested: Doppelvoice.exe double-clicked from dist/ launches the GUI cleanly (no Tkinter exception dialog), Settings opens automatically when .env is missing, log written to %APPDATA%\Roaming\Doppelvoice\logs\doppelvoice_YYYYMMDD.log.
Lesson
v0.3.0's onefile switch was tested on the dev box where sys.stderr is a real TTY. The crash only surfaced for fresh .exe users via the windowed bootloader. Onefile + console=False deserves an explicit smoke test in CI — tracked for v0.4.
Full changelog: CHANGELOG.md