CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/coding-policy

General-purpose coding policy for Baruch's AI agents

Quality

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

error-handling.mdrules/

alwaysApply:
Yes

Error Handling

Specific Exceptions

  • Catch specific exception types, never bare catch-all handlers
  • Let unexpected exceptions propagate

Outer-Boundary Carve-Out

  • Narrow exception for outer-boundary process contracts
  • Applies when a process boundary's caller reads non-zero exit OR invalid stdout as a silent-failure signal (agent-runner prechecks, network-protocol stdout contracts, IPC handlers)
  • A propagating unexpected exception silently disables the contract
  • Use the language's narrowest "everything except interrupts" form — Python except Exception:, or the analogous form in other languages
  • Never except BaseException: (or its equivalent that traps interrupts); KeyboardInterrupt and SystemExit must propagate so processes stay killable
  • Preconditions (all required):
    1. The catch line, the suppressor line, or a comment directly above either carries the literal grep token outer-boundary-process-contract
    2. Where a linter requires a catch-all suppressor, it sits attached to the catch by whichever placement the formatter permits, never separated from the catch by any other line:
      • Catch line, where the formatter keeps a trailing comment there — Python/Ruff # noqa: BLE001 on the except Exception: line
      • Immediately-preceding line, where the formatter relocates a same-line trailing comment off the catch's opening brace — TypeScript/ESLint under Prettier // eslint-disable-next-line directly above the catch
    3. A comment directly above the catch — or directly above the suppressor, when precondition 2 places the suppressor immediately above the catch — names three things:
      • caller's silent-failure shape
      • what catch emits
      • why propagation breaks contract
    4. Handler at outermost process boundary — never inner function
  • Every other catch in the file still uses specific exception types

Shell Error Handling

  • Every shell script opens with set -euo pipefail (except under the carve-out below)
  • Never suppress a failure — no || true, no || :, no 2>/dev/null standing in for a handler
  • A command that can legitimately fail gets an explicit if or case on its exit code, never blanket suppression
  • Distinguish an expected non-result from a tool failure — grep exits 1 on no-match and 2 on error, and || true collapses both, so an unreadable file or a bad regex reads as "nothing found"
  • Silencing a tool's diagnostic while explicitly handling its failure is not suppression: cmd 2>/dev/null || { echo "<actionable message>" >&2; exit 1; } replaces a worse message with a better one
  • Fail visibly does not require exit non-zero — best-effort work that legitimately continues past a failure emits a warning to stderr, never nothing
  • An EXIT trap's final command status becomes the script's exit status — end cleanup handlers with return 0 so cleanup never rewrites the outcome
  • Narrow exception for aggregate-reporting scripts that drop set -e
  • Applies when a script runs independent checks and reports an aggregate (test harnesses, multi-engine diagnostics gates)
  • Preconditions (all required):
    1. Each check is independent — a later one's result never depends on an earlier one having passed
    2. The script captures each check's exit code explicitly and exits non-zero when any check failed
    3. It keeps set -uo pipefail — only -e is dropped
    4. A setup step whose failure would silently corrupt the run rather than loudly abort it — a temp dir spliced onto PATH, a value that defaults to something dangerous — carries its own explicit failure check. A temp dir used only as a path for later file operations already fails loudly on first use and needs none
  • Every other shell script still opens with set -euo pipefail
  • Narrow exception for || true on a source of the script under test
  • Applies when sourcing runs that script's own set -euo pipefail in the harness's shell, and its entry-point guard then returns non-zero under the -e it just enabled
  • Preconditions (all required):
    1. The suppressed command is the source itself, never an assertion or a command under test
    2. set +e follows on the next line, restoring the harness's own discipline
    3. The harness takes the set -e carve-out above
  • Every other || true in a harness still converts to an explicit exit-code check

Actionable Messages

  • Error messages must tell the user what to do, not just what went wrong
  • Bad: "File not found"
  • Good: "Config file not found at ~/.config/app.toml — run app init to create one"

Graceful Fallback

  • When multiple approaches exist, try alternatives before failing
  • Example: try the preferred tool, fall back to an alternative, then fail with a clear message listing what was tried

Structured Logging

  • Log at appropriate levels: DEBUG for internals, INFO for progress, WARN for recoverable issues, ERROR for failures
  • Include enough context to diagnose without reproducing: input parameters, relevant state, error details
  • Never log secrets, tokens, passwords, or credentials — not even at DEBUG level

README.md

tile.json