Skip to main content
Anti-pattern diagnostics highlight code that technically compiles but is considered problematic: it may cause subtle bugs, break service lifetimes, or obscure intent. Most are warnings or suggestions.
Rules marked ⚠️ are warnings by default. Rules marked πŸ’‘ are suggestions. Rules marked βž– are off by default.
V3/V4: βœ“ / βœ“Warns when error-handling operators like Effect.catchAll, Effect.catch, or Effect.mapError are applied to an Effect whose error channel is never. The handler can never be triggered, which signals a logic error or dead code.
V3/V4: βœ“ / βœ“Effect.fn and Effect.fnUntraced create reusable named functions. Calling them immediately as an IIFE (immediately invoked function expression) defeats that purpose β€” use Effect.gen directly instead.
The quick fix replaces the Effect.fn(...)() call with Effect.gen.
V3/V4: βœ“ / βœ“Warns when the deprecated first-parameter adapter (_) is used inside Effect.gen. The adapter was required in older versions of Effect but is now just an alias for pipe and should be removed.
V3/V4: βœ“ / βœ“Warns when an Effect value appears in the error channel (E) of another Effect. The failure channel is intended to hold failure types (plain data), not executable computations. An Effect in the failure channel is never run and suggests a design mistake.
V3/V4: βœ“ / βœ“Detects nested Effect values in a void success channel. When a function returns void, any Effect returned inside it is silently discarded β€” it will never be executed, creating a hard-to-spot floating effect.
V3/V4: βœ“ / βœ“Warns when a catch callback (e.g., in Effect.tryPromise, Effect.try) returns the global Error type. Untagged errors merge together in the failure channel and lose type safety. Use a tagged error class instead.
V3/V4: βœ“ / βœ“Warns when the global Error type appears in the failure channel of an Effect type annotation. Like globalErrorInEffectCatch, untagged errors are indistinguishable from each other and cannot be handled precisely.
V3/V4: βœ“ / βœ“Detects when one layer inside a Layer.mergeAll call provides a service that another layer in the same call requires. Layer.mergeAll builds layers in parallel, so inter-layer dependencies are not satisfied. Move the dependent layer into a Layer.provideMerge call after the mergeAll.
V3/V4: βœ“ / βœ“Detects implementation services (internal dependencies) that are leaked through the public API of a service’s methods. When a service method requires an internal service from every caller, it exposes internal concerns to consumers. Resolve these dependencies at layer creation time instead.
V3/V4: βœ“ / βœ“Warns when Effect.provide is chained multiple times on the same effect. Chaining provide can cause service scope and lifecycle issues because each call creates a separate scope. Compose all layers into one and provide them in a single call.
V3/V4: βœ“ / βœ“Warns when a return statement inside an Effect.gen generator returns an Effect-able value, resulting in a nested Effect<Effect<...>>. This is almost always unintentional β€” use return yield* to execute and unwrap the inner effect.
The quick fix adds yield* before the returned expression.
V3 only Β Β·Β  V4: β€”Suggests using Runtime methods instead of calling Effect.runSync, Effect.runPromise, or similar functions inside an Effect context. Inside a generator, effects can simply be yielded. When you need to run a child effect using a specific runtime, use Effect.runtime and then the corresponding Runtime.* method.
V3 only Β Β·Β  V4: β€”Suggests using Effect-based Schema methods (e.g., Schema.decodeUnknown) instead of the synchronous variants (e.g., Schema.decodeUnknownSync) inside Effect generators. The sync methods throw on failure, bypassing Effect’s typed error channel. The Effect-based methods propagate errors through the channel with proper types.
V3 only Β Β·Β  V4: β€”Suggests using Layer.scoped instead of Layer.effect when Scope appears in the layer’s requirements channel. Layer.scoped is the correct constructor for layers that manage scoped resources; using Layer.effect leaves Scope in the requirements, forcing callers to supply it.
V3/V4: βœ“ / βœ“Warns when Effect.provide with a Layer is used outside of application entry points. Calling Effect.provide inside library code or service implementations can break scope lifetimes. All layers should be composed and provided once at the application entry point.This rule is off by default because there are valid use cases for Effect.provide in non-entry-point code (for example, test helpers). Enable it when you want to enforce strict layer discipline:
V3/V4: βœ“ / βœ“Discourages the use of try/catch inside Effect.gen generators. Exception-based error handling bypasses Effect’s typed error channel, making errors invisible to the type system. Use Effect.try, Effect.tryPromise, Effect.catch, or Effect.catchTag instead.
V3/V4: βœ“ / βœ“Warns when a catch callback (e.g., in Effect.tryPromise, Effect.try) returns unknown. An unknown error type is too wide to handle precisely. Narrow the type or wrap the error in a tagged class to make it useful in the error channel.