microsoft / microsoft/TypeScript

Debug Failure: "No error for last overload signature" crash when CustomTypeOptions.resources uses typeof on a large (~10k line) JSON file

Open
#63,195 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Needs More Info
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

## Bug Report

**TypeScript version:** 5.7.2 (also reproduced on 6.0.0-beta)
**i18next version:** 24.2.2
**react-i18next version:** 15.4.0
**Node:** 22.9.0

---

## Summary

TypeScript crashes with an internal `Debug Failure` when:
1. A `.d.ts` file augments i18next's `CustomTypeOptions.resources` using `typeof` on a large JSON file (~10k lines), and
2. TypeScript resolves the `t()` function's overloads against that resource type.

This is a compiler crash — not a type error surfaced to the user — so it always represents a broken invariant inside the checker.

---

## Reproduction

### File structure

```
src/
i18next.d.ts
public/assets/locales/en/translation.json ← ~10,000 lines, deeply nested
```

### `src/i18next.d.ts`

```ts
import type translation from '../public/assets/locales/en/translation.json';

declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: 'translation';
resources: {
translation: typeof translation;
};
}
}
```

### `tsconfig.app.json` (relevant parts)

```json
{
"compilerOptions": {
"moduleResolution": "bundler",
"resolveJsonModule": true,
"paths": {
"@locales/*": ["./public/assets/locales/*"]
}
},
"include": ["src"]
}
```

### Running `tsc --noEmit`

```
error TS2Function: Debug Failure. No error for last overload signature.
```

The process exits non-zero. No useful file/line information is attached to the diagnostic.

---

## Key observations

| Condition | Crashes? |
|-----------|----------|
| `typeof` on the full 10,085-line JSON | ✅ Yes |
| Replaced with a small hand-written type (same shape, ~20 keys) | ❌ No |
| `CustomTypeOptions` tuned with `returnNull: false`, `returnEmptyString: false`, `jsonFormat: "v4"` | ✅ Still crashes |
| `import type` instead of `import` | ✅ Still crashes |
| `resolveJsonModule` toggled | ✅ Still crashes |

The crash is **scale-triggered**: the combination of i18next's multi-overload `t()` signature and the deeply-nested union type produced by `typeof largeJson` causes the overload checker to reach an assertion it cannot satisfy.

---

## Why this is a TypeScript bug

`Debug Failure` diagnostics are internal `Debug.assert()` calls that should **never** reach the user. Regardless of how complex or unusual the input types are, the compiler must either:
- produce a proper type error, or
- succeed silently.

Crashing with an assertion failure when resolving overloads against a large `typeof` type is a broken invariant in the checker.

---

## Workarounds (all unsatisfactory)

- Commit with `--no-verify` to skip the typecheck step
- Replace `typeof translation` with a hand-maintained `TranslationKeys` type (defeats the purpose of auto-typed i18n)
- Suppress with `// @ts-ignore` across all call sites

---

## Additional context

The `t()` function in i18next 24.x has dozens of overloads that distribute over the resource namespace union. When the resource type has thousands of deeply-nested keys (as is common in production i18n files), the overload resolution cartesian-products the key space and appears to hit an unchecked branch in the "last overload must produce an error" logic.

A stack trace from the crash (abbreviated):

```
TypeError: Debug Failure. No error for last overload signature.
at resolveOverload (typescript/lib/typescript.js)
at getResolvedSignature (typescript/lib/typescript.js)
at checkCallExpression (typescript/lib/typescript.js)
```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the crash with the described i18next declaration, large JSON resource, and `tsc --noEmit`. Start at `resolveOverload` in `typescript/lib/typescript.js`, then trace `getResolvedSignature` and `checkCallExpression`; done means the same overload-resolution case no longer produces an internal Debug Failure and instead succeeds or reports a normal diagnostic.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.