CNA-BUG-067: Math argument failures throw a mix of Sharp Runtime and std:: exception types that differs between near-identical functions
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
BoundingBox throws Sharp Runtime ArgumentException types as XNA does, but BoundingSphere::CreateFromPoints, BoundingFrustum::GetCorners and the perspective builders throw std::invalid_argument or std::out_of_range.
- Identifier
CNA-BUG-067- Category
- Bug
- Subsystem
- Math & geometry
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- The exception types thrown by the math module's argument checks (CreateFromPoints, GetCorners, the Matrix::CreatePerspective* builders and the indexed overloads)
Expected behaviour
XNA 4.0 throws the ArgumentException family for these argument errors (for example ArgumentOutOfRangeException from CreatePerspectiveFieldOfView, read from its IL). CNA's own CHECKLIST.md records System::ArgumentOutOfRangeException as the majority precedent for out-of-range indexers and lists the std::out_of_range outliers as a known, unresolved inconsistency.
Actual behaviour at TARGET
BoundingBox::CreateFromPoints(empty list):System::ArgumentException;BoundingBox::GetCorners(std::vector<Vector3>&)(fewer than eight):System::ArgumentOutOfRangeException.BoundingSphere::CreateFromPoints(empty list):std::invalid_argument;BoundingFrustum::GetCorners(std::vector<Vector3>&):std::out_of_range.- The ten guards in
Matrix::CreatePerspective,CreatePerspectiveFieldOfViewandCreatePerspectiveOffCenter:std::invalid_argument. - The array overloads of
Vector2/3/4::TransformandTransformNormal,Curve::ComputeTangentand theCurveKeyCollectionindex checks:std::out_of_range.
Sharp Runtime's System::ArgumentException derives from System::SystemException and System::Exception, i.e. from std::exception but not from std::invalid_argument (next at 41b918c9, not pinned by TARGET), so no single catch clause short of std::exception handles a math argument error. The C ABI maps all of them to CNA_RESULT_INVALID_ARGUMENT, with category RANGE for std::out_of_range and ARGUMENT for the others.
Source locations
modules/math/src/BoundingBox.cpp— BoundingBox::CreateFromPoints and BoundingBox::GetCorners(std::vector<Vector3>&)modules/math/src/BoundingSphere.cpp— BoundingSphere::CreateFromPoints: std::invalid_argumentmodules/math/src/BoundingFrustum.cpp— BoundingFrustum::GetCorners(std::vector<Vector3>&): std::out_of_rangemodules/math/src/Matrix.cpp— the CreatePerspective* guards: std::invalid_argumentCHECKLIST.md— the mixed out-of-range precedent recorded as a known, unresolved inconsistencymodules/c-api/src/CnaCApiDetail.hpp— CallWithExceptionBarrier: the result and category per exception family
Evidence
Checked by reading at 009d40f5; nothing was built or executed for this entry. Every throw in modules/math/src was listed and classified; the tests assert each current type from both sides (BoundingBoxTests the System types, BoundingSphereTests, BoundingFrustumTests and MatrixTests the std types).
Focused reproduction
Illustrative; not compiled or run for this entry.
std::vector<Vector3> none;
try { BoundingBox::CreateFromPoints(none); } catch (const System::ArgumentException&) { /* caught */ }
try { BoundingSphere::CreateFromPoints(none); } catch (const System::ArgumentException&) { /* not caught: std::invalid_argument */ }
Current tests
BoundingBoxTests.cpp expects System::ArgumentException and System::ArgumentOutOfRangeException; BoundingSphereTests.cpp expects std::invalid_argument; BoundingFrustumTests.cpp expects std::out_of_range; MatrixTests.cpp expects std::invalid_argument. The inconsistency is therefore pinned, not merely untested.
Regression test
Choose one family per XNA contract (the Sharp Runtime ArgumentException family, as CHECKLIST.md's majority precedent suggests), change the throw sites and the four suites' expectations together, and add C ABI checks that the result category stays stable.
Blast radius
C++ callers that catch a specific exception type around these functions. The C ABI result code is the same for every family; only the error category differs. Normal inputs are unaffected.
Workaround
Catch std::exception (or both families) around math calls that validate their arguments.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Deep dives
- Game class and lifecycle: exceptions
- Known issues
- Bug index