Skip to content

Enforce Effect.fnUntraced for functions returning Effect.gen - #9506

Merged
tim-smart merged 3 commits into
mainfrom
agent/nelson/c2774db17cdb
Oct 18, 2026
Merged

tim-smart merged 3 commits into
mainfrom
agent/nelson/c2774db17cdb

Conversation

@tim-smart

@tim-smart tim-smart commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Makes functions that return Effect.gen a type-check error and points them at Effect.fnUntraced.

Config

  • effectFnOpportunity is set to error with effectFn: ["untraced"]. The default ["span"] option only flags functions that already end in Effect.withSpan(...), so before this change the rule caught almost nothing. With untraced it reports any named function, method or object property that returns Effect.gen.
  • The rule is set in tsconfig.base.json and in each config that has its own @effect/language-service plugin block (tests, ai-docs, scripts, scratchpad). A child plugins array replaces the base one, so the base setting alone doesn't reach them.
  • ignoreEffectErrorsInTscExitCode is now false in tsconfig.base.json and tsconfig.tests.json, so pnpm check fails on violations. This applies to every Effect diagnostic at error severity in package sources and tests, not just this rule. No other Effect errors are reported today, so nothing else breaks.

Source changes

50 call sites across effect (McpServer, cluster, eventlog, persistence), @effect/platform-node, @effect/platform-bun, @effect/sql-pg, @effect/docgen and one bundle fixture are converted using the language service's own quick fix. A second commit converts the 174 test sites (81 files) the same way, with no production source changes. Effect.gen and Effect.fnUntraced both run the generator under suspend, so runtime behavior is the same. The one difference: parameter destructuring now happens when the effect runs instead of when the function is called. Trailing .pipe(...) steps become fnUntraced pipeables. Point-free steps are wrapped as (_) => f(_), because fnUntraced passes the call arguments to each pipeable.

Validation

  • pnpm check, pnpm lint and the tests for the touched packages pass (94 files, 2889 tests).
  • The 81 converted test files and the 25 suites importing the converted helpers pass. pg and NodeRedis integration suites pass when run one at a time, except for container-startup hook timeouts in Client.integration.test.ts, which also happen locally without these changes.
  • A temporary test-file helper returning Effect.gen fails pnpm check.
  • With temporary probes in a package source and in ai-docs (an arrow, a function declaration and an object method, each returning Effect.gen), pnpm check reports all six as effectFnOpportunity errors and exits 2. It exits 0 once they're removed.
  • Docgen output for @effect/opentelemetry matches main.

Closes EFF-2446

@changeset-bot

changeset-bot Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9471927

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 33 packages
Name Type
effect Patch
@effect/platform-node Patch
@effect/platform-bun Patch
@effect/sql-pg Patch
@effect/docgen Patch
@effect/opentelemetry Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-cloudflare Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/ai-typesafe Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/platform-browser Patch
@effect/platform-deno Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/doctest Patch
@effect/graphql-generator Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-janitor effect-janitor Bot added the 4.0 label Oct 18, 2026
effect-janitor[bot]
effect-janitor Bot previously approved these changes Oct 18, 2026
effect-janitor[bot]
effect-janitor Bot previously approved these changes Oct 18, 2026
@tim-smart
tim-smart force-pushed the agent/nelson/c2774db17cdb branch from 47a897f to 9471927 Compare October 18, 2026 20:55
@tim-smart tim-smart changed the title Set effectFnOpportunity diagnostic to error Enforce Effect.fnUntraced for functions returning Effect.gen Oct 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
arbitrary-combinators.ts 39.08 KB 39.08 KB 0.00 KB (0.00%)
basic.ts 7.02 KB 7.02 KB 0.00 KB (0.00%)
batching.ts 10.81 KB 10.81 KB 0.00 KB (0.00%)
brand.ts 6.71 KB 6.71 KB 0.00 KB (0.00%)
cache.ts 11.33 KB 11.33 KB 0.00 KB (0.00%)
config.ts 22.52 KB 22.52 KB 0.00 KB (0.00%)
differ.ts 21.60 KB 21.60 KB 0.00 KB (0.00%)
http-client.ts 23.99 KB 23.99 KB 0.00 KB (0.00%)
http-router.ts 35.65 KB 35.65 KB 0.00 KB (0.00%)
logger.ts 11.68 KB 11.68 KB 0.00 KB (0.00%)
metric.ts 9.16 KB 9.16 KB 0.00 KB (0.00%)
optic.ts 6.93 KB 6.93 KB 0.00 KB (0.00%)
pubsub.ts 15.77 KB 15.77 KB 0.00 KB (0.00%)
queue.ts 12.59 KB 12.59 KB 0.00 KB (0.00%)
schedule.ts 11.77 KB 11.77 KB 0.00 KB (0.00%)
schema-bigdecimal.ts 13.81 KB 13.81 KB 0.00 KB (0.00%)
schema-binary.ts 40.55 KB 40.55 KB 0.00 KB (0.00%)
schema-class.ts 21.31 KB 21.31 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 32.38 KB 32.38 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 27.59 KB 27.59 KB 0.00 KB (0.00%)
schema-string-transformation.ts 15.06 KB 15.03 KB +0.04 KB (+0.24%)
schema-string.ts 12.07 KB 12.07 KB 0.00 KB (0.00%)
schema-template-literal.ts 16.29 KB 16.29 KB 0.00 KB (0.00%)
schema-toArbitrary.ts 38.60 KB 38.60 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 25.66 KB 25.66 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 20.54 KB 20.54 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 20.73 KB 20.73 KB 0.00 KB (0.00%)
schema-toFormatter.ts 20.84 KB 20.84 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 25.46 KB 25.46 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 20.83 KB 20.83 KB 0.00 KB (0.00%)
schema.ts 20.50 KB 20.50 KB 0.00 KB (0.00%)
stm.ts 13.87 KB 13.87 KB 0.00 KB (0.00%)
stream.ts 10.10 KB 10.10 KB 0.00 KB (0.00%)

@tim-smart
tim-smart merged commit 679f956 into main Oct 18, 2026
12 of 13 checks passed
@tim-smart
tim-smart deleted the agent/nelson/c2774db17cdb branch October 18, 2026 21:08
brandhaug added a commit to brandhaug/b2b-saas-starter that referenced this pull request Oct 25, 2026
## pnpm-workspace.yaml (default)

## Dependency Updates

| Package | From | To | Type |
| --- | --- | --- | --- |
| `@effect/platform-node` | 4.0.5 | 4.0.6 | patch |
| `@tanstack/react-router` | 1.170.45 | 1.170.46 | patch |
| `@tanstack/react-start` | 1.169.3 | 1.169.4 | patch |
| `ai` | 7.0.148 | 7.0.149 | patch |
| `effect` | 4.0.5 | 4.0.6 | patch |
| `effectful-better-auth` | 1.0.7 | 1.0.8 | patch |

## Release Notes

<details>
<summary><b>@<!---->effect/platform-node</b> (4.0.5 → 4.0.6)</summary>

### Patch Changes

- [#9506](Effect-TS/effect#9506)
[`679f956`](Effect-TS/effect@679f956)
Thanks @<!---->tim-smart! - Use `Effect.fnUntraced` for internal
functions that returned `Effect.gen`.

- [#9262](Effect-TS/effect#9262)
[`51930c0`](Effect-TS/effect@51930c0)
Thanks @<!---->effect-bot! - Return a typed multipart parse error
instead of a defect when a multipart request is missing its boundary.

- [#9402](Effect-TS/effect#9402)
[`d1201f0`](Effect-TS/effect@d1201f0)
Thanks @<!---->effect-bot! - Release writables created by
`NodeSink.fromWritable` and `fromWritableChannel` when upstream fails or
the sink is interrupted, preserving the original exit cause. Writables
using `endOnDone: false` remain open. Preserve stream body encoding
errors in the Node HTTP client instead of reporting transport errors
caused by request cleanup.

- [#9575](Effect-TS/effect#9575)
[`c29ddd8`](Effect-TS/effect@c29ddd8)
Thanks @<!---->tim-smart! - Add streaming request payloads to `HttpApi`.
An endpoint can declare `HttpApiSchema.StreamUint8Array` or the new
`HttpApiSchema.StreamNdjson({ schema })` as its `payload`, and the
handler receives a lazy `Stream` that reads the body as it pulls. Bad
NDJSON lines fail the stream with `HttpApiSchemaError` (400). The new
`maxBytes` and `maxElementBytes` limits fail it with the new
`HttpApiPayloadTooLarge` (413), and a `content-length` over `maxBytes`
is rejected before the handler runs. `StreamNdjson` also works as a
success response.
  
`HttpApiClient` sends a `Stream` payload without buffering it and infers
the stream's requirements. `HttpApiTest` passes stream payloads through
unbuffered. `OpenApi.fromApi` marks streaming request bodies with `x-

…[full
notes](https://github.com/Effect-TS/effect/releases/tag/%40effect/platform-node%404.0.6)

</details>

<details>
<summary><b>@<!---->tanstack/react-router</b> (1.170.45 →
1.170.46)</summary>

### Patch Changes

- [#8670](TanStack/router#8670)
[`32a3360`](TanStack/router@32a3360)
- Reference agent skills in other packages by their `intent load`
identifier (`@tanstack/<package>#<skill>`) instead of relative file
links that break once packages are installed.

- [#8671](TanStack/router#8671)
[`689a7c5`](TanStack/router@689a7c5)
- Publish the `@tanstack/react-router` agent skills (`react-router`,
`compositions/router-query`, `lifecycle/migrate-from-react-router`),
which were missing from the package's `files` list.

- Updated dependencies
\[[`32a3360`](TanStack/router@32a3360)]:
    -   @<!---->tanstack/[email protected]

</details>

<details>
<summary><b>@<!---->tanstack/react-start</b> (1.169.3 →
1.169.4)</summary>

### Patch Changes

- [#8670](TanStack/router#8670)
[`32a3360`](TanStack/router@32a3360)
- Reference agent skills in other packages by their `intent load`
identifier (`@tanstack/<package>#<skill>`) instead of relative file
links that break once packages are installed.

- Updated dependencies
\[[`32a3360`](TanStack/router@32a3360),
[`689a7c5`](TanStack/router@689a7c5),
[`ed55775`](TanStack/router@ed55775),
[`63a886d`](TanStack/router@63a886d),
[`d9b07e8`](TanStack/router@d9b07e8)]:
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]
    -   @<!---->tanstack/[email protected]

</details>

<details>
<summary><b>effect</b> (4.0.5 → 4.0.6)</summary>

### Patch Changes

- [#9674](Effect-TS/effect#9674)
[`ce13a48`](Effect-TS/effect@ce13a48)
Thanks @<!---->effect-bot! - Allow `Response.AllParts`, `Response.Part`
and `Response.StreamPart` to be called without a toolkit, decoding tool
call and tool result parts for any tool name with `unknown` parameters
and results.

- [#9696](Effect-TS/effect#9696)
[`f3bbbb4`](Effect-TS/effect@f3bbbb4)
Thanks @<!---->gcanti! - Fix `Array.unionWith` calling custom
equivalence callbacks with values from the wrong input or in the wrong
order.

- [#9511](Effect-TS/effect#9511)
[`5547315`](Effect-TS/effect@5547315)
Thanks @<!---->sledorze! - Speed up field copying in `Data.Class`,
`Data.Error`, `Request.Class` and `Persistable` constructors.

- [#9743](Effect-TS/effect#9743)
[`6093cfb`](Effect-TS/effect@6093cfb)
Thanks @<!---->effect-bot! - Fix `AsyncResult` equality treating
unrelated `Equal` values with a matching tag and hash as equal.

- [#9607](Effect-TS/effect#9607)
[`30319d5`](Effect-TS/effect@30319d5)
Thanks @<!---->effect-bot! - Fix Effect atoms dropping the latest
exposed success when an asynchronous run fails, so an `initialValue` or
a success published with `get.setSelf` remains available as the
failure's previous success.

- [#9313](Effect-TS/effect#9313)
[`74a7596`](Effect-TS/effect@74a7596)
Thanks @<!---->effect-bot! - Preserve Reactivity and global layers when
replacing an atom runtime layer through registry initial values, so
injected test layers retain shared invalidation and global services.

- [#9190](https://github.com

…[full
notes](https://github.com/Effect-TS/effect/releases/tag/effect%404.0.6)

</details>

---
*This PR was auto-generated by
[catalog-update-action](https://github.com/brandhaug/catalog-update-action).*

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
wmaurer added a commit to wmaurer/effect that referenced this pull request Oct 26, 2026
The effectFnOpportunity diagnostic is now an error (Effect-TS#9506), so helpers
that return Effect.gen must use the Effect.fnUntraced form.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant