Skip to content

VNX-391: Unchecked Error Condition

An exception is caught and silently discarded: a Java catch block holding only a TODO or auto-generated comment (plainly empty ones are reported by VNX-390), or a broad Python except whose whole body is pass.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-391
Severity Medium
SARIF level warning
Kind sast
Languages Java, Python
CWE CWE-391
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags error-handling cwe-391
Source internal/sast/rules/vnx-391.rego

Overview

VNX-391 maps to CWE-391: Unchecked Error Condition. It reports an exception that is caught and then thrown away. In Java that is a catch block which holds only a TODO/FIXME or auto-generated comment (beside blanks or a discarded e.toString()), or an empty or no-op body that runs longer than VNX-390 looks. A Java catch that is plainly empty (on one line, across a few blank lines, or with the brace on its own line) or whose only statement is a discarded e.toString()/e.getMessage() is reported by VNX-390 instead: it is the same defect, and CWE-390 (Detection of Error Condition Without Action) names it more exactly, so each such catch is one finding. In Python it is a bare except:, except Exception or except BaseException (alone or in a tuple) whose whole body is pass or ....

Not reported: a handler that logs, rethrows, returns or records anything; a Java catch variable named ignored, ignore, expected or unused (an explicit discard); a body with an explanatory comment, or a Python pass or except line carrying a trailing comment other than TODO/FIXME (# nosec, # noqa, a reason), which are documented decisions; a Python except of a specific type such as ImportError or KeyError; contextlib.suppress; test files, comments and strings.

Why This Matters

A swallowed exception turns a failure into silent success. The caller carries on with half-written data, a missing configuration or an unauthenticated session, and nothing in the logs says why. Broad handlers also swallow programming errors, so bugs that would have crashed loudly in testing hide in production.

What Gets Flagged

} catch (IOException e) {           // FLAGGED
    // TODO handle this
}

} catch (Exception e) {             // FLAGGED
    // Auto-generated catch block
}

try {
    ledger.write(invoice);
} catch (Exception e) {}            // reported by VNX-390, not here
try:
    os.remove(path)
except Exception:                   # FLAGGED
    pass

Remediation

  1. Catch the specific exception the call can raise, and handle it: retry, fall back, or return an error the caller checks.
  2. If the failure is genuinely harmless, log it at debug level or name the variable ignored and add a comment saying why.
  3. In Python, prefer contextlib.suppress(SpecificError) for a deliberate, narrow discard.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-391
// nosec vnx-391

Or record an ignore rule: vulnetix ignore add --rule vnx-391 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-391.rego, cli/internal/sast/docs/vnx-391.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.