FilletEdge fails for a small set of reasons, and almost none of them are the command’s fault. The command creates a tangent surface between polysurface edges, then trims and joins the original faces to the fillet surfaces. That last step is where most failures live: the fillet rolls along the edge, tries to trim and join with adjacent surfaces, and gives up when the geometry it meets is not what the command expects. Before you file a bug or rebuild the model, run a two-minute diagnostic on the edge itself.
What FilletEdge actually requires
McNeel’s Rhino 8 documentation for FilletEdge states the input is polysurface or extrusion edges. The command’s own tips are the closest thing to a prerequisite list:
- Fillet from the largest radius to the smallest radius across a model.
- Remove edges you can before filleting, using MergeAllCoplanarFaces or simpler surfacing.
- Make sure there is enough room for the fillet surface to trim and join with adjacent surfaces.
- Angle relationships between surfaces, sharpness of the bend in the rail around corners, and rail type all affect the result.
Two of those tips are geometry checks in disguise. “Enough room” is a radius-versus-edge-length check. “Angle relationships” is a continuity check. The documentation also notes that if you set a radius larger than the edge radius at a handle location, the handle turns dark red and displays the maximum radius allowed at that location. That is the command telling you the local geometry cannot support the radius you asked for, before you ever hit Enter.
The ChainEdges option “automatically selects connected edges based on continuity.” If your edges are not continuous, chaining stops. That is a useful early signal: if double-clicking an edge does not select the tangent chain you expected, the problem is upstream of the fillet.
Naked edges: the gap the fillet cannot bridge
A naked edge is an edge not connected to another edge. McNeel’s ShowEdges documentation defines it exactly that way and adds the operational consequence: solid objects have no naked edges. If ShowEdges reports naked edges on a closed polysurface you intended to be solid, the object is not closed, and FilletEdge is being asked to roll a tangent surface across a gap.
Run ShowEdges with the Naked edges option, then use ZoomNaked to step through each one. ZoomNaked finds and marks naked edges; its Mark option adds point objects at each end of the current edge. Those point objects are the important part. They give you a persistent marker at the exact location of the gap, which survives a view change and can be measured.
Measure the gap. If it is below your file tolerance, Join should have closed it and did not, which usually means the surfaces were never within tolerance in the first place. If it is above tolerance, you have a modeling error, not a filleting error. Either way, the fix is upstream: rebuild, match, or re-trim the surfaces so the edge is actually shared.
Non-manifold edges are a separate failure mode. ShowEdges defines them as edges shared by more than two faces. A fillet rolling into a non-manifold junction has no unambiguous pair of adjacent surfaces to trim and join against. ZoomNonManifold finds and marks them the same way ZoomNaked does. Treat a non-manifold edge as a stop-work condition before filleting.
G1 discontinuity: tangent is not the same as smooth enough
FilletEdge produces a tangent surface. Tangent means G1: the surfaces meet with matching first derivatives, so the transition is smooth in the mathematical sense. But the command needs the input edges to behave predictably as the fillet rolls along them. Where two adjacent faces meet at a shallow angle, or where the rail bends sharply around a corner, the trim-and-join step has less room to work. The documentation lists “sharpness of the bend in the rail around corners” as a factor in any particular case.
G1 discontinuity at the edge itself is the harder problem. If the two faces meeting at the edge are not tangent-continuous, the fillet surface has to reconcile two different surface normals along its length. The result is either a failure or a fillet that looks acceptable in a shaded viewport and fails in a curvature analysis or a downstream STEP export.
The practical check is to examine the edge before filleting. In Rhino, use the curvature graph on the edge curves, or explode the polysurface and inspect the surface match at the shared boundary. If the surfaces are G0 (position only) rather than G1, the fillet is being asked to do a matching job that belongs to the surface modeler. Fix the surface continuity first.
The EdgeTolerance check
Rhino’s file tolerance is the distance below which two points are considered coincident. It governs Join, it governs the tolerance at which edges are considered shared, and it is the number against which ShowEdges decides whether an edge is naked. If your file tolerance is 0.001 units and your model was built at 0.01, you will see naked edges everywhere and FilletEdge will fail on edges that look perfectly closed on screen.
Before blaming FilletEdge, do this:
- Check DocumentProperties > Units > Absolute tolerance. Note the value.
- Run ShowEdges with Naked edges on the target polysurface.
- If naked edges appear, run ZoomNaked with Mark to place points at the gap ends.
- Measure the distance between the marked points with Distance or a linear dimension.
- Compare that distance to the absolute tolerance.
If the measured gap is at or below tolerance and the edge still reads as naked, the surfaces are not actually joined. Re-run Join and check the command line for the number of edges joined. If the gap is above tolerance, the model has a real gap and no amount of fillet radius adjustment will close it.
This check costs about two minutes per problem edge. Rebuilding a failed fillet by hand, or re-exporting a model that fails downstream because the fillet was never watertight, costs considerably more. The tolerance check is the cheapest diagnostic in the workflow.
What to do when the check passes and FilletEdge still fails
If the edge is not naked, not non-manifold, and the surfaces are G1, the remaining causes are radius and rail geometry. The documentation’s own guidance applies: fillet largest radius to smallest, remove edges with MergeAllCoplanarFaces before filleting, and confirm there is room for the fillet surface to trim and join. A radius that exceeds the local edge radius will be flagged by the dark red handle. A radius that fits locally but collides with a neighboring fillet will not be flagged, and that is a sequencing problem, not a tolerance problem.
RailType matters here. DistFromEdge, RollingBall, and DistBetweenRails determine how the intersection is computed. RollingBall is the default mental model for most users, but it is not always the right one for a given corner. If a fillet fails at a corner and succeeds along the straight run, try a different rail type before rebuilding the surface.
Scripting the check
For teams running the same diagnostic across many files, RhinoCommon exposes the underlying data. The RhinoCommon API is the reference for the object model; the relevant classes are the Brep edge and topology types that report edge adjacency and continuity. A repeatable pre-fillet check can iterate the Brep edges, flag naked and non-manifold edges, and report the file tolerance alongside the count. That turns a manual two-minute check into a batch operation, which matters when you are validating a library of components rather than a single model.
The API reference is the primary source for method signatures and return types. Do not rely on forum snippets for the exact behavior of a given method; check the API page for the version you are running.
FAQ
Why does FilletEdge fail on an edge that looks closed?
Because “looks closed” is a display judgment and naked-edge detection is a tolerance judgment. Run ShowEdges with Naked edges and compare the gap to the file’s absolute tolerance.
Does a larger file tolerance fix naked edges?
It can make Join succeed where it previously failed, but it also loosens every other tolerance-dependent operation in the file. Change tolerance deliberately, not as a workaround, and re-check downstream exports afterward.
What is the difference between a naked edge and a non-manifold edge?
A naked edge is not connected to another edge. A non-manifold edge is shared by more than two faces. Both are reported by ShowEdges, and both will stop FilletEdge from trimming and joining cleanly.
Can I fillet a G0 edge?
You can try, but the fillet surface has to reconcile two different surface normals along its length. The result is unreliable. Fix the surface continuity before filleting.
Why does double-clicking an edge not select the whole chain?
ChainEdges selects connected edges based on continuity. If the chain stops, the edges are not continuous at that point. That is a continuity problem, not a selection problem.