Skip to content
Back to skills

Error Handling

ASecurity

Грамотное покрытие кода обработкой ошибок (try/catch/finally) и структурным логированием без «тихих» падений. Куда ставить try/catch (границы I/O/внешних вызовов/парсинга/транзакций) и куда НЕ ставить, нормализация ошибок (typed errors, cause, stack, unknown в catch), async/finally/cleanup, ретраи/таймауты для транзиентных сбоев; грамотная расстановка логов — уровни, контекст, correlation id, лог один раз на границе, без секретов/PII. Use при добавлении/ревью error handling и логирования в бэ...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
devopstypescriptreactnodedockerapi

Works with

  • api

Security analysis

A100/100

Scanned September 11, 2026

npx -y skills add Vitammiin/agent-vorcl-flow --skill error-handling --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Error Handling?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Error Handling
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vitammiin-error-handling-agent-vorcl-flow/badge)](https://www.skillsdirectory.com/skills/vitammiin-error-handling-agent-vorcl-flow)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: error-handling
description: Грамотное покрытие кода обработкой ошибок (try/catch/finally) и структурным логированием без «тихих» падений. Куда ставить try/catch (границы I/O/внешних вызовов/парсинга/транзакций) и куда НЕ ставить, нормализация ошибок (typed errors, cause, stack, unknown в catch), async/finally/cleanup, ретраи/таймауты для транзиентных сбоев; грамотная расстановка логов — уровни, контекст, correlation id, лог один раз на границе, без секретов/PII. Use при добавлении/ревью error handling и логирования в бэке (Node/Fastify) и фронте (React).
version: 1.0.0
---

# Навык: Error Handling & Logging

Цель — **надёжный** код без «тихих» падений и с **грамотной расстановкой логов**: понятно, что упало, почему и с каким контекстом — без шума и утечек секретов.

## Куда ставить try/catch (и куда НЕ ставить)
- **Ставь на границах**, где ошибка ожидаема и её есть чем обработать: I/O (сеть, файлы, БД), внешние API, парсинг/десериализация (`JSON.parse`, zod), транзакции, места, где нужен cleanup.
- **НЕ оборачивай всё подряд.** Программные ошибки (баги, нарушенные инварианты) пусть всплывают до глобального обработчика — не глотай их локально. Один осмысленный `try` на операцию лучше, чем `try` вокруг каждой строки.
- **Не дублируй обработку:** ловишь и пробрасываешь — не логируй на каждом слое (см. «Логи один раз»).

## Никаких «тихих» падений
- **Пустой `catch {}` запрещён.** В catch всегда одно из трёх: (1) **обработать** — осмысленный фолбэк + лог; (2) **пробросить** (`throw`), возможно обогатив: `throw new AppError('...', { cause: error })`; (3) **преобразовать** в доменную ошибку/`Result`. «Проглотил и пошёл дальше» — только с явным комментарием, почему это безопасно.
- Не теряй причину: `new Error(msg, { cause })` сохраняет **ссылку** на исходную ошибку (её `message`/`stack`/тип доступны через `err.cause`), но **не сшивает** стеки в один трейс — логгер должен явно сериализовать цепочку `cause` (pino err-serializer это делает; `console.log` без `util.inspect` — нет).
- В прикладном коде бросай **только `Error`** (или наследников), иначе теряются `stack` и тип. Исключение: фреймворки бросают спец-объекты для control-flow (Next `redirect()`/`notFound()`) — их **не** трогай и не проглатывай в `catch` без re-throw.
- В TypeScript `catch (error)` имеет тип `unknown` — сузь перед использованием (`error instanceof Error ? … : …`), не обращайся к `error.message` вслепую.

## Нормализация ошибок
- Доменные классы: `class AppError extends Error { code; httpStatus; context }`. Отличай **operational** (ожидаемые: 4xx, недоступность внешнего) от **programmer** (баги → 5xx, алерт).
- На границе наружу (HTTP) — единый error-handler: маппинг ошибки в статус + **безопасное** тело (без стека/внутренностей клиенту). Fastify — `setErrorHandler`; Next App Router — `error.tsx` на уровне сегмента, для ошибок корневого layout нужен `global-error.tsx`, а в route handlers/Server Actions ошибки нормализуй явно (структурированный ответ/`throw` с маппингом), не полагаясь на `error.tsx`.
- Валидация входа (zod) на границе → предсказуемые 400, а не 500 глубоко внутри.
- **i18n сообщений:** наружу отдавай стабильный машинный `code` (+ параметры), а человекочитаемый текст **локализуй** на границе по локали запроса; **логи не локализуй** (один язык, обычно English). Подробнее — скилл **i18n**.

## Async, finally, cleanup
- `await` внутри `try`; не смешивай `.then().catch()` с `try/await` бессистемно.
- Освобождение ресурсов (коннект, файл, лок, таймер) — в `finally`, чтобы не текло при ошибке.
- Параллельно: `Promise.allSettled` — когда важны все результаты; `Promise.all` — когда любой сбой должен прервать. На уровне процесса лови `unhandledRejection`/`uncaughtException`, но **не продолжай работу**: состояние процесса после них неопределённо — залогируй и **заверши процесс** (graceful shutdown → `exit 1`), пусть оркестратор/PM2/Docker перезапустит. Это не «глобальный catch, чтобы работать дальше».

## Транзиентные сбои: ретраи/таймауты
- Внешние вызовы — с **таймаутом** (`AbortSignal.timeout`). Ретрай — только на **транзиентных** ошибках (сеть/таймаут/`5xx`/`429`), с экспоненциальным бэкоффом + jitter и лимитом попыток; на `4xx`/бизнес-ошибках не ретрай. **Мутации** ретрай только при **идемпотентности по эффекту** (idempotency key/дедуп на сервере), а не потому что «это просто повтор».
- Каскады — circuit breaker/деградация; не держи пользователя в бесконечном ожидании.

## Грамотная расстановка логов
- **Структурные логи** (JSON: pino/структурный logger), не голый `console.log` в проде. Поля: `level`, `msg`, `err` (message+stack+cause), `context` (ids, операция), `requestId`/correlation id.
- **Уровни:** `error` — сбой, требующий внимания; `warn` — аномалия с фолбэком; `info` — **значимые бизнес-события** (лог на каждый запрос — это отдельный access-log на выделенном канале/с сэмплингом, а не `info` по умолчанию, иначе шум); `debug` — детали диагностики (в проде выкл./по флагу). Не логируй всё на `error`.
- **Логируй один раз** — на слое, где есть контекст и где ошибка **обрабатывается** (обычно верхняя граница/handler). Пробрасываешь — **не** логируй здесь же (иначе дубли на каждом уровне).
- **Что логировать:** какая операция, ключевые id, длительность важных операций, исход; ошибку — целиком (`err` со `stack` и **цепочкой `cause`** — убедись, что сериализатор логгера разворачивает `cause`, иначе первопричина потеряется).
- **Что НЕ логировать:** пароли, токены, ключи, PII, чувствительные тела/полный payload без нужды — маскируй/редактируй. На горячих путях — сэмплируй.
- Логи не для управления потоком: не парси текст лога как сигнал.

## Фронтенд (React)
- **Error boundary** на дерево UI (класс-компонент или `react-error-boundary`): ловит **только** ошибки рендера/жизненного цикла/конструкторов дочерних компонентов — **не** ловит ошибки в event handlers, async (`setTimeout`/промисы), при SSR и в самом boundary. Показывает фолбэк, репортит.
- Ошибки хендлеров/async и данных (fetch/react-query) — вне boundary: `try/catch` в хендлере, состояние `error` у react-query (повтор, дружелюбный UI; не «пустой экран» и не стек пользователю), глобальный `window.onerror`/`onunhandledrejection`.

## Бэкенд (Node/Fastify)
- Единый `setErrorHandler` — маппинг доменных ошибок → статус + безопасное тело; логирование там же (один раз).
- Процессные обработчики (`unhandledRejection`, `uncaughtException`, сигналы) → лог + graceful shutdown (дренаж коннектов).
- Не «съедай» ошибки в middleware/репозиториях молча.

## Анти-паттерны (ищи и убирай)
- `catch (e) {}` / `catch (e) { console.log(e) }` без обработки/проброса; `catch`, возвращающий `null`/`undefined` и скрывающий сбой.
- `throw 'строка'`; потеря `cause`; логирование одной ошибки на 3 уровнях; лог секретов/PII; `try` вокруг кода, который не бросает; необработанные промис-реджекты; незакрытые ресурсы при ошибке.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.