Safeguard
Developer Tools•

What does useUnknownInCatchVariables change in TypeScript?

useUnknownInCatchVariables types caught errors as unknown, forcing a check before use. Why that helps Node services avoid leaking or mishandling errors.

Safeguard Security Team
3 min read

It makes the variable in a catch clause typed unknown instead of any. You must narrow it before reading properties. In a Node.js service that prevents code from assuming every thrown value is an Error, which is how crashes inside error handlers and leaked internals often start.

What the flag does

The TypeScript tsconfig reference describes it plainly: catch clause variables become unknown, so you narrow before use. Its example:

try {
  riskyCall();
} catch (err) {
  if (err instanceof Error) {
    console.log(err.message);
  }
}

It is one of the nine flags that strict turns on, so most strict projects already have it.

Why any was risky

JavaScript can throw anything: a string, a number, an object, or null. With any, the compiler lets you write err.message.toLowerCase() even when err is a string. The handler then throws a second error, often outside the code path your tests cover. Error handlers are code that runs when something is already wrong, so a bug there is expensive.

Safe handling in an HTTP service

  1. Narrow first. Use instanceof Error for errors you expect. Use a small helper that converts anything into a safe message string.
  2. Log the detail, return a generic message. Send the client a short fixed message and an id. Keep stack traces and internal messages in logs only.
  3. Do not echo the error back. Messages from databases, file systems and parsers can include paths, queries or values.
  4. Preserve the cause. When you wrap, pass the original so logs keep the chain.
  5. Rethrow what you cannot handle. Swallowing errors with an empty catch hides failures, including failed authorization checks.

A helper for step 1:

export function errorMessage(value: unknown): string {
  if (value instanceof Error) return value.message;
  if (typeof value === "string") return value;
  return "Unknown error";
}

How this ties to Node behavior

Node.js treats an uncaught exception as a crash by default. The process docs say the event is a crude mechanism meant for last resort cleanup and that it is not safe to resume normal operation afterwards. Good catch blocks reduce how often you get there, but they do not replace a restart policy.

Adopting it

If you are not on strict yet, enable useUnknownInCatchVariables alone and fix the errors. They usually appear in a small number of files, and each fix is a few lines. See Is TypeScript strict mode a security setting for the rest of the group.

Limits

The flag only affects catch clauses. Promise rejections handled with .catch(handler) receive any in many type definitions, so narrow there too. A separate lint rule covers promises that nobody handles at all, which the post on floating promises explains.

Quick check

Is useUnknownInCatchVariables part of strict?

Yes. The TypeScript reference lists it among the nine flags enabled by strict.

Should I send error.message to the client?

Generally no. Internal messages can reveal paths, queries or values. Return a generic message and log the detail.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.