Location, confirmed at current HEAD. include/lin/lin.hpp:83 (class ErrInvalidFrame : public std::runtime_error), used throughout src/lin.cpp (e.g. lines 35, 59, 61, 63, 65, 112, 115) and
declared as the throw behavior on ValidateFrame/from_message in lin.hpp:151,160; also
src/relay.cpp:60 throws a bare std::invalid_argument from parse_protocol.
Finding. The audit's §3.4 error-sentinel-model matrix notes that most RELAY-conformant C++ ports
follow the std::error_code/error_category pattern the spec's §5.2/§18.2 error-wrapping model is
built around, "except where protocol errors are thrown as exceptions instead (cpp-CAN
ErrInvalidFrame, cpp-LIN ErrInvalidFrame/dead ErrNoResponse) — a real §18.2 deviation, not
cosmetic." Re-checked against current HEAD: this repo's ErrInvalidFrame is not a std::error_code
value at all — it's a distinct exception type derived from std::runtime_error, thrown from every
frame-validation and message-conversion call site rather than returned. A caller written against the
spec's std::error_code convention (as sibling protocols use) has no way to catch this condition
without knowing to catch (const lin::ErrInvalidFrame&) specifically, which is a materially different
calling convention than the rest of the ecosystem. The companion ErrNoResponse dead-code angle on
this same exception-vs-sentinel mismatch is already tracked separately as issue #34
([cpp-LIN-03]) — this issue is scoped to the broader exception-vs-std::error_code architecture
choice for ErrInvalidFrame specifically, which #34 does not cover.
Recommendation. Convert ErrInvalidFrame (and the std::invalid_argument thrown from
parse_protocol) to the std::error_code/error_category pattern used elsewhere in the C++ port
family, returning it rather than throwing, so callers can handle it uniformly with the rest of the
RELAY C++ ecosystem per §18.2's error-wrapping model.
Filed from the 2026-07-29 ecosystem audit register; independently re-verified against current HEAD before filing.
Location, confirmed at current HEAD.
include/lin/lin.hpp:83(class ErrInvalidFrame : public std::runtime_error), used throughoutsrc/lin.cpp(e.g. lines 35, 59, 61, 63, 65, 112, 115) anddeclared as the throw behavior on
ValidateFrame/from_messageinlin.hpp:151,160; alsosrc/relay.cpp:60throws a barestd::invalid_argumentfromparse_protocol.Finding. The audit's §3.4 error-sentinel-model matrix notes that most RELAY-conformant C++ ports
follow the
std::error_code/error_categorypattern the spec's §5.2/§18.2 error-wrapping model isbuilt around, "except where protocol errors are thrown as exceptions instead (cpp-CAN
ErrInvalidFrame, cpp-LINErrInvalidFrame/deadErrNoResponse) — a real §18.2 deviation, notcosmetic." Re-checked against current HEAD: this repo's
ErrInvalidFrameis not astd::error_codevalue at all — it's a distinct exception type derived from
std::runtime_error, thrown from everyframe-validation and message-conversion call site rather than returned. A caller written against the
spec's
std::error_codeconvention (as sibling protocols use) has no way to catch this conditionwithout knowing to
catch (const lin::ErrInvalidFrame&)specifically, which is a materially differentcalling convention than the rest of the ecosystem. The companion
ErrNoResponsedead-code angle onthis same exception-vs-sentinel mismatch is already tracked separately as issue #34
(
[cpp-LIN-03]) — this issue is scoped to the broader exception-vs-std::error_codearchitecturechoice for
ErrInvalidFramespecifically, which #34 does not cover.Recommendation. Convert
ErrInvalidFrame(and thestd::invalid_argumentthrown fromparse_protocol) to thestd::error_code/error_categorypattern used elsewhere in the C++ portfamily, returning it rather than throwing, so callers can handle it uniformly with the rest of the
RELAY C++ ecosystem per §18.2's error-wrapping model.
Filed from the 2026-07-29 ecosystem audit register; independently re-verified against current HEAD before filing.