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 swallow errors into a silent, misleading degraded state
A caught error must either propagate or set explicit state the caller checks — never be logged and ignored while callers proceed as if nothing failed.
Bad example
| 1 | async init(): Promise<void> { |
| 2 | try { |
| 3 | await this.client.connect(); |
| 4 | this.isConnected = true; |
| 5 | } catch (error) { |
| 6 | this.logError(`Failed to connect: ${error}`); |
| 7 | this.logInfo('Using in-memory cache as fallback'); // no such fallback exists |
| 8 | } |
| 9 | } |
| 10 |
|
| 11 | async subscribe(channel: string) { |
| 12 | await this.init(); |
| 13 | await this.client.subscribe(channel); // throws ClientClosedError, masking the real cause |
| 14 | } |
Explanation (EN)
Catching an error internally and merely logging it lets the caller continue as if the operation succeeded, so the real failure surfaces later as an unrelated, confusing error (or not at all) instead of at the point it actually happened.
Objašnjenje (HR)
Ako se greška interno uhvati i samo zaloga, pozivatelj nastavlja kao da je operacija uspjela, pa se stvarni problem pojavi kasnije kao nepovezana, zbunjujuća greška (ili uopće ne) umjesto na mjestu gdje se stvarno dogodio.
Good example
| 1 | async init(): Promise<void> { |
| 2 | try { |
| 3 | await this.client.connect(); |
| 4 | this.isConnected = true; |
| 5 | } catch (error) { |
| 6 | this.logError(`Failed to connect: ${error}`); |
| 7 | throw error; // let the caller decide how to degrade |
| 8 | } |
| 9 | } |
| 10 |
|
| 11 | async subscribe(channel: string) { |
| 12 | if (!this.isConnected) { |
| 13 | throw new Error('Cannot subscribe: client is not connected'); |
| 14 | } |
| 15 | await this.client.subscribe(channel); |
| 16 | } |
Explanation (EN)
Either rethrow the error so the caller can decide how to degrade, or expose explicit state (like a connected flag) that dependent code checks before proceeding — never claim a fallback exists that the code doesn't actually implement.
Objašnjenje (HR)
Ili ponovno baci grešku da pozivatelj sam odluči kako degradirati, ili izloži eksplicitno stanje (npr. connected flag) koje ovisan kod provjerava prije nastavka — nikad ne tvrdi da postoji fallback koji kod zapravo ne implementira.
Exceptions / Tradeoffs (EN)
A genuinely implemented fallback (e.g. an actual in-memory cache with real read/write paths) is fine to swallow into — the point is the fallback must actually exist for the operation being performed.
Iznimke / Tradeoffi (HR)
Stvarno implementiran fallback (npr. pravi in-memory cache sa stvarnim read/write putevima) je u redu progutati grešku u njega — poanta je da fallback stvarno mora postojati za operaciju koja se izvodi.