Errors
OCCT reports failure two ways: exceptions (Standard_Failure and its subclasses) for invalid input, and status flags (IsDone(), Error(), HasErrors()) on algorithms that can fail on valid input.
Exceptions
C++ exceptions never cross into .NET on their own. Every wrapper catches them and NetOcc throws an OcctException when the call returns:
sequenceDiagram
participant App as your code
participant Proxy as C# proxy
participant Wrapper as native wrapper
participant OCCT
App->>Proxy: new gp_Dir(0, 0, 0)
Proxy->>Wrapper: P/Invoke
Wrapper->>OCCT: gp_Dir(0, 0, 0)
OCCT-->>Wrapper: throw Standard_ConstructionError
Wrapper-->>Proxy: type and message, via a callback
Proxy-->>App: throw OcctException
try
{
var flat = new BRepPrimAPI_MakeBox(0, 10, 10).Shape();
}
catch (OcctException e) when (e.Is<Standard_DomainError>())
{
// OcctType names the class OCCT threw, OcctMessage has its message
caught = $"{e.OcctType}: {e.OcctMessage}";
}
| Member | Gives |
|---|---|
OcctType |
the class OCCT threw: Standard_ConstructionError, or std::exception for the standard library's |
OcctMessage |
OCCT's message, if it gave one |
Is<T>() |
whether it's a T or a subclass, by OCCT's class hierarchy |
Is<T> follows the hierarchy, so catching a base class catches its subclasses:
try
{
var zero = new gp_Dir(0, 0, 0);
}
catch (OcctException e)
{
type = e.OcctType; // "Standard_ConstructionError"
construction = e.Is<Standard_ConstructionError>(); // true
domain = e.Is<Standard_DomainError>(); // true: its base class
range = e.Is<Standard_RangeError>(); // false
}
flowchart LR
failure[Standard_Failure] --- domain[Standard_DomainError]
failure --- numeric[Standard_NumericError]
failure --- program[Standard_ProgramError]
failure --- notDone[StdFail_NotDone]
domain --- construction[Standard_ConstructionError]
domain --- nullObject[Standard_NullObject]
domain --- noSuchObject[Standard_NoSuchObject]
domain --- typeMismatch[Standard_TypeMismatch]
domain --- dimension[Standard_DimensionError]
domain --- range[Standard_RangeError]
range --- outOfRange[Standard_OutOfRange]
range --- negative[Standard_NegativeValue]
range --- nullValue[Standard_NullValue]
numeric --- divide[Standard_DivideByZero]
numeric --- overflow[Standard_Overflow]
program --- notImplemented[Standard_NotImplemented]
| Thrown for | Usually |
|---|---|
Standard_ConstructionError |
a degenerate input: a zero vector as a direction, coincident points |
Standard_DomainError |
an argument outside what the method accepts: a zero-size box |
Standard_OutOfRange |
an index outside a collection's bounds |
Standard_TypeMismatch |
a wrong cast: TopoDS.Face of an edge |
Standard_NoSuchObject |
a key a map doesn't have |
StdFail_NotDone |
the result of an algorithm that failed |
Builders that fail
Builders check their input and record why they failed, without throwing:
// builders check their input and say why they failed, without throwing
var point = new gp_Pnt(1, 1, 1);
var edge = new BRepBuilderAPI_MakeEdge(point, point);
var done = edge.IsDone(); // false
var why = edge.Error(); // BRepBuilderAPI_LineThroughIdenticPoints
// asking a failed builder for its result throws StdFail_NotDone
Action result = () => edge.Edge();
| Builder | Why it failed |
|---|---|
BRepBuilderAPI_MakeEdge |
Error(): BRepBuilderAPI_EdgeError |
BRepBuilderAPI_MakeWire |
Error(): BRepBuilderAPI_WireError, e.g. disconnected edges |
BRepBuilderAPI_MakeFace |
Error(): BRepBuilderAPI_FaceError, e.g. a non-planar wire |
BRepFilletAPI_MakeFillet |
NbFaultyContours(), StripeStatus(i) |
BRepAlgoAPI_* |
HasErrors(), HasWarnings(), GetReport() |
Where failure is possible on valid input, as with fillets whose radius doesn't fit, check before asking for the result:
// a radius the box can't take
var fillet = new BRepFilletAPI_MakeFillet(box);
fillet.Add(20, edge);
fillet.Build();
TopoDS_Shape result = fillet.IsDone() ? fillet.Shape() : box; // keep the box unrounded
Booleans report through a message report instead:
// booleans report through HasErrors and HasWarnings
var cut = new BRepAlgoAPI_Cut(box, new TopoDS_Shape()); // a null tool
var failed = cut.HasErrors(); // true
What isn't checked
OCCT doesn't check everything, and a C++ crash ends the process: it can't be caught.
Warning
A null shape has no type: new TopoDS_Shape().ShapeType() crashes, as it does in C++, where it dereferences a null handle (exploring it, Location() and NbChildren() are safe). Check IsNull() on shapes an algorithm may leave empty, and null returns such as BRep_Tool.Triangulation of a face without a mesh.
NetOcc checks what it adds: its collection indexers, array lengths for fixed-size parameters, and size_t values on x86 throw OcctException rather than read out of bounds.