> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Effect-TS/tsgo/llms.txt
> Use this file to discover all available pages before exploring further.

# Correctness diagnostics

> Diagnostics that catch wrong, unsafe, or structurally invalid Effect code patterns.

Correctness diagnostics flag code that is structurally invalid or likely to cause runtime bugs. Most are errors by default and block compilation when an Effect type is misused.

<Info>
  Rules marked ❌ are errors by default. Rules marked ⚠️ are warnings. Rules marked ➖ are off by default and must be enabled in `diagnosticSeverity`.
</Info>

## `anyUnknownInErrorContext`

**Severity:** ➖ off by default  ·  **V3/V4:** ✓ / ✓

Detects `any` or `unknown` types in the error (`E`) or requirements (`R`) channels of an `Effect`. These imprecise types defeat the purpose of Effect's typed error and dependency channels.

Enable this rule to enforce fully typed channels across your codebase.

```typescript theme={null}
// ❌ Violation — error channel is `unknown`
declare const myEffect: Effect.Effect<number, unknown, never>

// ✅ Correct — use a concrete error type
declare const myEffect: Effect.Effect<number, DatabaseError, never>
```

To enable:

```jsonc theme={null}
{ "diagnosticSeverity": { "anyUnknownInErrorContext": "warning" } }
```

***

## `classSelfMismatch`

**Severity:** ❌ error  ·  **Fix:** 🔧  ·  **V3/V4:** ✓ / ✓

Ensures that the `Self` type parameter passed to `Effect.Service`, `Effect.Tag`, `ServiceMap.Service`, or Schema class constructors matches the class name. A mismatch breaks the service identity used internally by the Context system.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — Self parameter says "WrongName"
class Database extends Effect.Service<WrongName>()("Database", {
  effect: Effect.succeed({ query: () => Effect.void })
}) {}

// ✅ Correct — Self parameter matches the class name
class Database extends Effect.Service<Database>()("Database", {
  effect: Effect.succeed({ query: () => Effect.void })
}) {}
```

The quick fix updates the type argument to match the class name automatically.

***

## `duplicatePackage`

**Severity:** ⚠️ warning  ·  **V3/V4:** ✓ / ✓

Warns when multiple versions of an Effect-related package are present in the program's dependency graph. Duplicate packages cause services to have different identities in each copy, breaking `Context` lookups silently.

```
⚠️ Multiple versions of package 'effect' detected: 2.x.x, 3.x.x.
Consider cleaning up your lockfile, or add 'effect' to allowedDuplicatedPackages to suppress this warning.
```

If a duplicate is intentional (for example during a migration), add the package to `allowedDuplicatedPackages`:

```jsonc theme={null}
{ "allowedDuplicatedPackages": ["effect"] }
```

***

## `effectFnImplicitAny`

**Severity:** ❌ error  ·  **V3/V4:** ✓ / ✓

Mirrors TypeScript's `noImplicitAny` check for parameters inside `Effect.fn`, `Effect.fnUntraced`, and `Effect.fnUntracedEager` callbacks when no outer contextual function type provides the annotation. Requires `noImplicitAny: true` in `tsconfig.json`.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — `id` has implicit any type
const getUser = Effect.fn("getUser")(function* (id) {
  return yield* fetchUser(id)
})

// ✅ Correct — explicit type annotation
const getUser = Effect.fn("getUser")(function* (id: string) {
  return yield* fetchUser(id)
})
```

***

## `floatingEffect`

**Severity:** ❌ error  ·  **V3/V4:** ✓ / ✓

Detects `Effect` values that are created as standalone expression statements — neither yielded inside a generator nor assigned to a variable. A floating Effect is never executed and indicates a missing `yield*` or assignment.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — the effect is discarded
Effect.gen(function* () {
  Effect.log("hello") // floating: never executed
})

// ✅ Correct — yield* the effect to execute it
Effect.gen(function* () {
  yield* Effect.log("hello")
})
```

***

## `genericEffectServices`

**Severity:** ⚠️ warning  ·  **V3/V4:** ✓ / ✓

Prevents defining `Effect.Service` or `Effect.Tag` classes with type parameters. Generic services cannot be discriminated at runtime because different instantiations share the same tag identifier, leading to unexpected behavior when looking up services from `Context`.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — generic type parameter makes runtime discrimination impossible
class Repository<T> extends Effect.Service<Repository<T>>()("Repository", {
  effect: Effect.succeed({ findById: (id: string) => Effect.succeed({} as T) })
}) {}

// ✅ Correct — concrete service type
class UserRepository extends Effect.Service<UserRepository>()("UserRepository", {
  effect: Effect.succeed({ findById: (id: string) => Effect.succeed({} as User) })
}) {}
```

***

## `missingEffectContext`

**Severity:** ❌ error  ·  **V3/V4:** ✓ / ✓

Detects `Effect` values whose requirements channel (`R`) contains services that have not been provided. This is analogous to a missing import — the effect cannot run without those services.

```typescript theme={null}
import { Effect } from "effect"

class Database extends Effect.Service<Database>()("Database", {
  effect: Effect.succeed({ query: () => Effect.void })
}) {}

// ❌ Violation — Database is required but not provided
const program: Effect.Effect<void, never, never> = Effect.gen(function* () {
  const db = yield* Database
  yield* db.query()
})

// ✅ Correct — provide the Database layer
const program = Effect.gen(function* () {
  const db = yield* Database
  yield* db.query()
}).pipe(Effect.provide(Database.Default))
```

***

## `missingEffectError`

**Severity:** ❌ error  ·  **Fix:** 🔧  ·  **V3/V4:** ✓ / ✓

Detects `Effect` values whose error channel (`E`) contains error types that are not handled by the type expected at that position. This flags type-level mismatches where errors leak through unhandled.

```typescript theme={null}
import { Effect, Data } from "effect"

class NotFoundError extends Data.TaggedError("NotFoundError")<{}> {}
class ValidationError extends Data.TaggedError("ValidationError")<{}> {}

declare function findUser(): Effect.Effect<User, NotFoundError | ValidationError>

// ❌ Violation — ValidationError is unhandled
const result: Effect.Effect<User, NotFoundError> = findUser()

// ✅ Correct — handle or propagate all error types
const result: Effect.Effect<User, NotFoundError> = findUser().pipe(
  Effect.catchTag("ValidationError", () => Effect.fail(new NotFoundError()))
)
```

The quick fix adds the missing error types to the expected type.

***

## `missingLayerContext`

**Severity:** ❌ error  ·  **V3/V4:** ✓ / ✓

Detects `Layer` values whose input requirements (`RIn`) contain services that are not satisfied by the composed layers. Similar to `missingEffectContext` but for the layer graph.

```typescript theme={null}
import { Effect, Layer } from "effect"

class Config extends Effect.Service<Config>()("Config", {
  effect: Effect.succeed({ url: "http://localhost" })
}) {}

class HttpClient extends Effect.Service<HttpClient>()("HttpClient", {
  effect: Effect.gen(function* () {
    const config = yield* Config
    return { get: (path: string) => Effect.void }
  })
}) {}

// ❌ Violation — Config is required by HttpClient.Default but not provided
const AppLayer: Layer.Layer<HttpClient> = HttpClient.Default

// ✅ Correct — compose layers to satisfy requirements
const AppLayer: Layer.Layer<HttpClient> = HttpClient.Default.pipe(
  Layer.provide(Config.Default)
)
```

***

## `missingReturnYieldStar`

**Severity:** ❌ error  ·  **Fix:** 🔧  ·  **V3/V4:** ✓ / ✓

Suggests using `return yield*` for Effects that never succeed (success type is `never`). Using `return yield*` instead of just `yield*` signals a definitive exit point, improving type narrowing and tooling support for exhaustive pattern matching.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — yield* on a never-succeeding effect without return
const handle = Effect.gen(function* () {
  const result = yield* someEffect
  if (result === null) {
    yield* Effect.fail(new Error("null result")) // missing return
  }
  return result
})

// ✅ Correct — return yield* signals the function exits here
const handle = Effect.gen(function* () {
  const result = yield* someEffect
  if (result === null) {
    return yield* Effect.fail(new Error("null result"))
  }
  return result
})
```

***

## `missingStarInYieldEffectGen`

**Severity:** ❌ error  ·  **Fix:** 🔧  ·  **V3/V4:** ✓ / ✓

Detects bare `yield` (without `*`) inside Effect generator scopes. Inside `Effect.gen`, you must always use `yield*` to unwrap an Effect. Using `yield` without `*` returns the raw Effect object rather than executing it.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — bare yield, the effect is not executed
const program = Effect.gen(function* () {
  const value = yield Effect.succeed(42) // should be yield*
  return value
})

// ✅ Correct — yield* executes the effect and unwraps the value
const program = Effect.gen(function* () {
  const value = yield* Effect.succeed(42)
  return value
})
```

***

## `nonObjectEffectServiceType`

**Severity:** ❌ error  ·  **V3 only**  ·  **V4:** —

Ensures that the service type in `Effect.Service` is an object type (`{}`) and not a primitive. Effect's Context system requires object types to safely attach tag metadata. This rule is V3-only because V4's `ServiceMap.Service` handles primitives differently.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — service type is a primitive string
class ApiKey extends Effect.Service<ApiKey>()("ApiKey", {
  succeed: "my-api-key" // string is a primitive
}) {}

// ✅ Correct — wrap the value in an object
class ApiKey extends Effect.Service<ApiKey>()("ApiKey", {
  succeed: { value: "my-api-key" }
}) {}
```

***

## `outdatedApi`

**Severity:** ⚠️ warning  ·  **V3:** —  ·  **V4 only**

Detects usage of APIs that were removed or renamed in Effect V4. The diagnostic message includes the V3 API that was used and guidance on the V4 replacement. This rule is only active when the language service detects an Effect V4 project.

```typescript theme={null}
import { Effect } from "effect"

// ❌ Violation — Effect.tryCatchPromise was renamed in V4
const result = Effect.tryCatchPromise(
  () => fetch("/api"),
  (e) => new Error(String(e))
)

// ✅ Correct — use the V4 API
const result = Effect.tryPromise({
  try: () => fetch("/api"),
  catch: (e) => new Error(String(e))
})
```

***

## `overriddenSchemaConstructor`

**Severity:** ❌ error  ·  **Fix:** 🔧  ·  **V3/V4:** ✓ / ✓

Prevents overriding the constructor in classes that extend a Schema class (`Schema.Class`, `Schema.TaggedClass`, `Schema.TaggedError`, etc.). Overriding the constructor silently breaks the schema's decoding behaviour. Use a static factory method instead.

```typescript theme={null}
import { Schema } from "effect"

// ❌ Violation — constructor override breaks decoding
class User extends Schema.Class<User>("User")({
  id: Schema.String,
  name: Schema.String,
}) {
  constructor(data: { id: string; name: string }) {
    super(data) // this silently breaks decoding
  }
}

// ✅ Correct — use a static factory method
class User extends Schema.Class<User>("User")({
  id: Schema.String,
  name: Schema.String,
}) {
  static make(data: { id: string; name: string }): User {
    return new User(data)
  }
}
```

The quick fix removes the constructor override and replaces it with a static `new` method.
