Skip to content

KCL: union() rejects an extrude + sweep operand pair - a helical thread cannot be unioned into its own fastener #1316

Description

@OneCrew01

Summary

union() is rejected when one operand is a sweep() result and the other is an
extrude(). The practical consequence is that a helical thread cannot be unioned into
the shank it belongs to
, so a threaded fastener cannot exist as a single solid.

engine: The Zoo engine cannot handle this 3D union yet.  Please report this as an issue

The error text asks for a report, hence this issue.

Minimal repro

Two bodies. One extrude, one sweep along a helix(). Nothing else.

@settings(defaultLengthUnit = in, kclVersion = 2.0)

shank = startSketchOn(XY)
  |> circle(center = [0, 0], radius = 0.1875)
  |> extrude(length = 0.44)

th = helix(angleStart = 0, ccw = true, revolutions = 8, length = 0.43, radius = 0.21875, axis = Z)

ridge = startSketchOn(XZ)
  |> startProfile(at = [0.1875, 0.005])
  |> line(end = [0.03125, 0.022])
  |> line(end = [-0.03125, 0.022])
  |> close()
  |> sweep(path = th)

threadedStud = union([shank, ridge])   // rejected

Both operands build fine individually and render correctly as separate bodies. Only the
union is refused.

Same rejection with a loft operand

union([loft, extrude]) fails identically:

lo = startSketchOn(offsetPlane(XY, offset = 0.70)) |> circle(center = [0,0], radius = 0.19)
hi = startSketchOn(offsetPlane(XY, offset = 0.83)) |> circle(center = [0,0], radius = 0.31)
cone = loft([lo, hi])
body = startSketchOn(XY) |> circle(center = [0,0], radius = 0.19) |> extrude(length = 0.80)
joined = union([cone, body])   // rejected

This blocks flare seats, chamfer transitions and tapered hoods being joined to the
prismatic bodies they adjoin. It may or may not share a root cause with the sweep case,
but the symptom and error string are identical, so both are reported here rather than
split across two issues.

Impact

This is not cosmetic. Downstream of the sweep case:

  • a male thread cannot exist as one solid;
  • therefore a male/female thread pair cannot be evaluated for mesh or interference at
    all
    ;
  • so any threaded-fastener assembly is reduced to cosmetic thread geometry plus a plain
    bore, and must be labelled as such rather than presented as a validated joint.

We hit this building AN-4 and AN-6 flared-fitting assemblies (37 degree aviation flare
hardware). The thread is currently carried as a separate body with an explicit
"cosmetic thread representation" notice in the source, because there is no honest
alternative.

Related: #1294

#1294 reports the same engine
message on subtract() with cut-crossing tools and absolute-scale sensitivity. Further
measurement since then suggests the boolean limits are governed by resulting topology
rather than operand count
, which may be useful triage context:

Case Operands Result
78 circular cutters subtracted from one body, single call 78 works
2 cutters subtracted from a flange plate 2 works
2 cutters whose diameter exceeds the bar thickness (cut would sever the body) 2 rejected
2 cutters + 1 window cutter that would turn a plate into a closed frame 3 rejected
1 extrude + 1 sweep (this issue) 2 rejected

78 cutters in a single call succeeding while 2 fail is the part that seems worth
knowing: quantity is clearly not the variable.

Environment

  • KCL @settings(kclVersion = 2.0), default length unit in
  • Driven through the zoo-mcp server (mock_execute_kcl, execute_kcl,
    snapshot_of_kcl)
  • Reproduced repeatedly on 2026-07-30 and 2026-07-31

Note on mock execution

mock_execute_kcl returns success for both repros above before the engine rejects
them. If mock is intended as a pre-flight check, it does not currently cover this class
of failure - worth flagging separately if that is a surprise.

Suggested

Short term, a "known limitations" note on the
union() standard library page
covering operand kinds that are not yet supported would save the discovery hunt - the
same gap #1294 identifies for subtract().

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions