Skip to content

Latest commit

 

History

History
76 lines (57 loc) · 1.88 KB

File metadata and controls

76 lines (57 loc) · 1.88 KB

defensive.error-swallowing

Flags log-and-continue catch blocks.

  • Family: defensive
  • Severity: strong
  • Scope: file
  • Requires: file.tryCatchSummaries

How it works

The rule looks for small try/catch blocks where the catch clause only logs and then continues. That pattern records the failure but still suppresses it from callers.

Filesystem-existence probes are ignored, and boundary-heavy catches are downweighted rather than removed entirely.

Flagged example

export async function syncUser(id: string) {
  try {
    await pushUser(id);
  } catch (error) {
    logger.warn(error);
  }
}

Usually ignored

export async function syncUser(id: string) {
  try {
    await pushUser(id);
  } catch (error) {
    logger.error({ error, id });
    throw error;
  }
}

How to fix / do this better

Logging is not a substitute for control flow. If the caller still needs to know the operation failed, prefer one of these:

  • log and rethrow
  • return an explicit result type such as { ok: false, error }
  • handle the failure completely at this layer only when you can prove continuing is safe
export async function syncUser(id: string) {
  try {
    await pushUser(id);
  } catch (error) {
    logger.error({ error, id }, "failed to sync user");
    throw error;
  }
}

The key is to make failure visible in the API contract instead of only visible in logs.

Scoring

Each flagged catch uses the shared try/catch scoring helper, then the file total is capped at 8.

Benchmark signal

Small pinned rule benchmark (manifest):

  • Signal rank: #3 of 9
  • Signal score: 0.72 / 1.00
  • Best separating metric: findings / file (0.87)
  • Hit rate: 6/6 AI repos vs 3/5 mature OSS repos
  • Full results: rule signal report