Historical control-flow still uses bare ASSERT(0) without recovery or logging
Summary¶
There is still a broad class of historical control-flow debt where ASSERT(0)
is used as a placeholder for “should never happen” without a real recovery,
error-reporting, or logging path behind it.
This is distinct from BUG-034, which tracks release-silent catch (...)
patterns. BUG-035 tracks direct control-flow paths that fall into bare
assertions without exception handling at all.
Representative Live Sites¶
srchybrid/TreePropSheet.cppsrchybrid/TransferWnd.cppsrchybrid/SHAHashSet.cpp
These are representative anchors, not an exhaustive list.
Why This Matters¶
In debug builds, these sites surface as assert dialogs. In release builds, the assert usually disappears, leaving one of these outcomes:
- silent no-op behavior
- implicit fallthrough into whatever follows
- partially-updated UI or state with no operator-visible explanation
That makes the code harder to reason about and makes production failures harder to diagnose than they should be.
Intended Fix Direction¶
Do not replace every ASSERT(0) mechanically.
Preferred remediation pattern:
- keep assertion coverage where it still documents impossible invariants in debug builds
- add explicit recovery or early-return behavior for live runtime paths
- add logging where practical and useful
- convert a few high-value sites into explicit error handling helpers where a repeated pattern exists
Current Mainline Outcome¶
The first bounded diagnostics slice landed on main in commit 9992cb1
(BUG-034 BUG-035: add bounded runtime failure logs). Commit a962351
also hardened selected Unicode INI and UTF-8 decoding paths that previously had
weak release-mode behavior.
The collection-import slice also narrows one ownership/recovery path by making rejected imported collection entries explicitly importer-owned until accepted, so duplicate or invalid entries are disposed without changing the public collection API.
The collection-file import slice also turns missing file hashes and invalid AICH hash metadata into explicit release-mode policy: hashless entries are rejected and logged through the binary-entry skip path, while malformed optional AICH tags are logged and ignored without rejecting the rest of the entry.
The secure-ident slice also moves ClientCredits key/signature failure results
behind small seam helpers, preserving the existing failed-ident transitions
while avoiding implicit release-mode fallthrough on oversized inputs.
The server TCP packet slice also moves the CServerSocket packet-failure
continue/disconnect decision behind a small seam helper. This keeps the debug
assertions as invariant markers while making the release-mode behavior explicit
and covered by native tests.
The legacy WebServer search slice also moves unsupported file-type clearing, failed-start parameter ownership, generic exception fallback, and gzip fallback policy behind small seam helpers. The user-visible behavior stays compatible, but the release-mode control flow is now explicit and covered by native tests.
The Transfer window slice moves invalid primary/secondary view-state handling
behind TransferWndSeams. Bad persisted or runtime view ids now use explicit
release-mode fallbacks instead of only hitting debug assertions, and the
fallback policy is covered by native tests.
The 2026-05-01 release-readiness scan found no rollback-level regression in the
recent control-flow hardening slices. It does keep the client UDP unknown
exception path as the next practical release-silent target because that site
still combines a release-only catch (...) fallback with a debug-only
ASSERT(0) marker and verbose-gated diagnostics.
The client UDP slice landed on main in commit 6b76687 and narrows that
specific combined pattern: the debug assertion remains as an invariant marker,
but release-mode unexpected packet exceptions now force a diagnostic log through
the new ClientUDPSocketSeams policy. Native coverage for the policy landed in
emulebb-build-tests commit 6af34cc.
The server UDP slice landed on main in commit 16f50ba and narrows the same
release-mode pattern for CUDPSocket::ProcessPacketError: debug assertions
remain as invariant markers, while unexpected release exceptions now bypass the
verbose-only logging gate. Native coverage for the policy landed in
emulebb-build-tests commit 80bfa14.
The async socket helper-init slice landed on main in commit cf4bbb1 and
narrows another release-silent initialization failure: helper-window allocation
or construction exceptions in CAsyncSocketEx::InitAsyncSocketExInstance() now
keep their existing cleanup and failure return, but the release build records a
diagnostic log. Native policy coverage landed in emulebb-build-tests commit
ad49ff8.
This item is In Progress, not Done: the 2026-05-01 scan still finds 541
ASSERT(0) matches in current app source. Many are legitimate invariant checks,
but enough live control-flow sites remain that this should stay as a broad
hardening bucket with future targeted slices.
Relationship to Existing Items¶
BUG-034coverscatch (...)plusASSERT(0)silent exception swallowingBUG-002remains the focusedArchiveRecoveryrepresentative issue
BUG-035 exists to track the broader direct-control-flow ASSERT(0) debt that
is not primarily exception-driven.