Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Don't wrap a call in try/catch when the layer below already normalizes failures
Remove a try/catch when the underlying wrapper already absorbs errors into a safe value, so the catch is unreachable dead code.
Bad example
| 1 | // getPersonsByIds (via the fetch wrapper) already returns [] on any upstream error. |
| 2 | try { |
| 3 | const results = await getPersonsByIds(ids); |
| 4 | return res.json(results.map(format)); |
| 5 | } catch (error) { |
| 6 | // This branch can never run — the service never rejects. |
| 7 | return res.status(500).json({ error: 'Failed to fetch.' }); |
| 8 | } |
Explanation (EN)
If the service is contractually safe (resolves to `[]`/`null`, never rejects), the catch is unreachable. It adds noise, falsely implies the call can throw, and the dead 500 branch can mask the real contract from the next reader. Dead error paths also defeat coverage.
Objašnjenje (HR)
Ako je servis ugovorno siguran (razrjesava u `[]`/`null`, nikad ne odbacuje), catch je nedostupan. Dodaje sum, lazno sugerira da poziv moze baciti iznimku, a mrtva 500 grana moze sakriti stvarni ugovor od sljedeceg citatelja. Mrtve grane gresaka takoder kvare pokrivenost testovima.
Good example
| 1 | // Trust the contract: getPersonsByIds resolves to [] on failure. |
| 2 | const results = await getPersonsByIds(ids); |
| 3 | return res.json(results.map(format)); |
Explanation (EN)
With the redundant wrapper gone, the handler reads as what it is: a call that always resolves to a usable value. If you ever need a genuine error path, add it where an error can actually originate (e.g. inside the fetch wrapper), not as decoration around a call that can't fail.
Objašnjenje (HR)
Bez suvisnog omotaca, handler se cita onako kakav jest: poziv koji uvijek razrjesava u upotrebljivu vrijednost. Ako ti ikada zatreba prava grana za greske, dodaj je tamo gdje greska stvarno moze nastati (npr. unutar fetch omotaca), a ne kao ukras oko poziva koji ne moze pasti.
Notes (EN)
Verify the contract before deleting — read the wrapper to confirm it really swallows errors rather than assuming it does.
Bilješke (HR)
Provjeri ugovor prije brisanja — procitaj omotac da potvrdis da stvarno guta greske, a ne da to pretpostavljas.
Exceptions / Tradeoffs (EN)
Keep the try/catch if the call genuinely can throw (synchronous parsing, a wrapper that rethrows, JSON.parse on the result), or if you need to translate a thrown error into a domain-specific response.
Iznimke / Tradeoffi (HR)
Zadrzi try/catch ako poziv stvarno moze baciti iznimku (sinkrono parsiranje, omotac koji ponovno baca, JSON.parse nad rezultatom) ili ako trebas prevesti bacenu gresku u domenski specifican odgovor.