@wazir-dev/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) hide show
  1. package/AGENTS.md +111 -0
  2. package/CHANGELOG.md +14 -0
  3. package/CONTRIBUTING.md +101 -0
  4. package/LICENSE +21 -0
  5. package/README.md +314 -0
  6. package/assets/composition-engine.mmd +34 -0
  7. package/assets/demo-script.sh +17 -0
  8. package/assets/logo-dark.svg +14 -0
  9. package/assets/logo.svg +14 -0
  10. package/assets/pipeline.mmd +39 -0
  11. package/assets/record-demo.sh +51 -0
  12. package/docs/README.md +51 -0
  13. package/docs/adapters/context-mode.md +60 -0
  14. package/docs/concepts/architecture.md +87 -0
  15. package/docs/concepts/artifact-model.md +60 -0
  16. package/docs/concepts/composition-engine.md +36 -0
  17. package/docs/concepts/indexing-and-recall.md +160 -0
  18. package/docs/concepts/observability.md +41 -0
  19. package/docs/concepts/roles-and-workflows.md +59 -0
  20. package/docs/concepts/terminology-policy.md +27 -0
  21. package/docs/getting-started/01-installation.md +78 -0
  22. package/docs/getting-started/02-first-run.md +102 -0
  23. package/docs/getting-started/03-adding-to-project.md +15 -0
  24. package/docs/getting-started/04-host-setup.md +15 -0
  25. package/docs/guides/ci-integration.md +15 -0
  26. package/docs/guides/creating-skills.md +15 -0
  27. package/docs/guides/expertise-module-authoring.md +15 -0
  28. package/docs/guides/hook-development.md +15 -0
  29. package/docs/guides/memory-and-learnings.md +34 -0
  30. package/docs/guides/multi-host-export.md +15 -0
  31. package/docs/guides/troubleshooting.md +101 -0
  32. package/docs/guides/writing-custom-roles.md +15 -0
  33. package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
  34. package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
  35. package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
  36. package/docs/readmes/INDEX.md +99 -0
  37. package/docs/readmes/features/expertise/README.md +171 -0
  38. package/docs/readmes/features/exports/README.md +222 -0
  39. package/docs/readmes/features/hooks/README.md +103 -0
  40. package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
  41. package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
  42. package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
  43. package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
  44. package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
  45. package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
  46. package/docs/readmes/features/hooks/session-start.md +119 -0
  47. package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
  48. package/docs/readmes/features/roles/README.md +157 -0
  49. package/docs/readmes/features/roles/clarifier.md +152 -0
  50. package/docs/readmes/features/roles/content-author.md +190 -0
  51. package/docs/readmes/features/roles/designer.md +193 -0
  52. package/docs/readmes/features/roles/executor.md +184 -0
  53. package/docs/readmes/features/roles/learner.md +210 -0
  54. package/docs/readmes/features/roles/planner.md +182 -0
  55. package/docs/readmes/features/roles/researcher.md +164 -0
  56. package/docs/readmes/features/roles/reviewer.md +184 -0
  57. package/docs/readmes/features/roles/specifier.md +162 -0
  58. package/docs/readmes/features/roles/verifier.md +215 -0
  59. package/docs/readmes/features/schemas/README.md +178 -0
  60. package/docs/readmes/features/skills/README.md +63 -0
  61. package/docs/readmes/features/skills/brainstorming.md +96 -0
  62. package/docs/readmes/features/skills/debugging.md +148 -0
  63. package/docs/readmes/features/skills/design.md +120 -0
  64. package/docs/readmes/features/skills/prepare-next.md +109 -0
  65. package/docs/readmes/features/skills/run-audit.md +159 -0
  66. package/docs/readmes/features/skills/scan-project.md +109 -0
  67. package/docs/readmes/features/skills/self-audit.md +176 -0
  68. package/docs/readmes/features/skills/tdd.md +137 -0
  69. package/docs/readmes/features/skills/using-skills.md +92 -0
  70. package/docs/readmes/features/skills/verification.md +120 -0
  71. package/docs/readmes/features/skills/writing-plans.md +104 -0
  72. package/docs/readmes/features/tooling/README.md +320 -0
  73. package/docs/readmes/features/workflows/README.md +186 -0
  74. package/docs/readmes/features/workflows/author.md +181 -0
  75. package/docs/readmes/features/workflows/clarify.md +154 -0
  76. package/docs/readmes/features/workflows/design-review.md +171 -0
  77. package/docs/readmes/features/workflows/design.md +169 -0
  78. package/docs/readmes/features/workflows/discover.md +162 -0
  79. package/docs/readmes/features/workflows/execute.md +173 -0
  80. package/docs/readmes/features/workflows/learn.md +167 -0
  81. package/docs/readmes/features/workflows/plan-review.md +165 -0
  82. package/docs/readmes/features/workflows/plan.md +170 -0
  83. package/docs/readmes/features/workflows/prepare-next.md +167 -0
  84. package/docs/readmes/features/workflows/review.md +169 -0
  85. package/docs/readmes/features/workflows/run-audit.md +191 -0
  86. package/docs/readmes/features/workflows/spec-challenge.md +159 -0
  87. package/docs/readmes/features/workflows/specify.md +160 -0
  88. package/docs/readmes/features/workflows/verify.md +177 -0
  89. package/docs/readmes/packages/README.md +50 -0
  90. package/docs/readmes/packages/ajv.md +117 -0
  91. package/docs/readmes/packages/context-mode.md +118 -0
  92. package/docs/readmes/packages/gray-matter.md +116 -0
  93. package/docs/readmes/packages/node-test.md +137 -0
  94. package/docs/readmes/packages/yaml.md +112 -0
  95. package/docs/reference/configuration-reference.md +159 -0
  96. package/docs/reference/expertise-index.md +52 -0
  97. package/docs/reference/git-flow.md +43 -0
  98. package/docs/reference/hooks.md +87 -0
  99. package/docs/reference/host-exports.md +50 -0
  100. package/docs/reference/launch-checklist.md +172 -0
  101. package/docs/reference/marketplace-listings.md +76 -0
  102. package/docs/reference/release-process.md +34 -0
  103. package/docs/reference/roles-reference.md +77 -0
  104. package/docs/reference/skills.md +33 -0
  105. package/docs/reference/templates.md +29 -0
  106. package/docs/reference/tooling-cli.md +94 -0
  107. package/docs/truth-claims.yaml +222 -0
  108. package/expertise/PROGRESS.md +63 -0
  109. package/expertise/README.md +18 -0
  110. package/expertise/antipatterns/PROGRESS.md +56 -0
  111. package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
  112. package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
  113. package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
  114. package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
  115. package/expertise/antipatterns/backend/index.md +24 -0
  116. package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
  117. package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
  118. package/expertise/antipatterns/code/async-antipatterns.md +622 -0
  119. package/expertise/antipatterns/code/code-smells.md +1186 -0
  120. package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
  121. package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
  122. package/expertise/antipatterns/code/index.md +27 -0
  123. package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
  124. package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
  125. package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
  126. package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
  127. package/expertise/antipatterns/design/dark-patterns.md +1121 -0
  128. package/expertise/antipatterns/design/index.md +22 -0
  129. package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
  130. package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
  131. package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
  132. package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
  133. package/expertise/antipatterns/frontend/index.md +23 -0
  134. package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
  135. package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
  136. package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
  137. package/expertise/antipatterns/index.md +31 -0
  138. package/expertise/antipatterns/performance/index.md +20 -0
  139. package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
  140. package/expertise/antipatterns/performance/premature-optimization.md +623 -0
  141. package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
  142. package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
  143. package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
  144. package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
  145. package/expertise/antipatterns/process/index.md +23 -0
  146. package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
  147. package/expertise/antipatterns/security/index.md +20 -0
  148. package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
  149. package/expertise/antipatterns/security/security-theater.md +843 -0
  150. package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
  151. package/expertise/architecture/PROGRESS.md +70 -0
  152. package/expertise/architecture/data/caching-architecture.md +671 -0
  153. package/expertise/architecture/data/data-consistency.md +574 -0
  154. package/expertise/architecture/data/data-modeling.md +536 -0
  155. package/expertise/architecture/data/event-streams-and-queues.md +634 -0
  156. package/expertise/architecture/data/index.md +25 -0
  157. package/expertise/architecture/data/search-architecture.md +663 -0
  158. package/expertise/architecture/data/sql-vs-nosql.md +708 -0
  159. package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
  160. package/expertise/architecture/decisions/build-vs-buy.md +616 -0
  161. package/expertise/architecture/decisions/index.md +23 -0
  162. package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
  163. package/expertise/architecture/decisions/technology-selection.md +616 -0
  164. package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
  165. package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
  166. package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
  167. package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
  168. package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
  169. package/expertise/architecture/distributed/index.md +25 -0
  170. package/expertise/architecture/distributed/saga-pattern.md +797 -0
  171. package/expertise/architecture/foundations/architectural-thinking.md +460 -0
  172. package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
  173. package/expertise/architecture/foundations/design-principles-solid.md +649 -0
  174. package/expertise/architecture/foundations/domain-driven-design.md +719 -0
  175. package/expertise/architecture/foundations/index.md +25 -0
  176. package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
  177. package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
  178. package/expertise/architecture/index.md +34 -0
  179. package/expertise/architecture/integration/api-design-graphql.md +638 -0
  180. package/expertise/architecture/integration/api-design-grpc.md +804 -0
  181. package/expertise/architecture/integration/api-design-rest.md +892 -0
  182. package/expertise/architecture/integration/index.md +25 -0
  183. package/expertise/architecture/integration/third-party-integration.md +795 -0
  184. package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
  185. package/expertise/architecture/integration/websockets-realtime.md +791 -0
  186. package/expertise/architecture/mobile-architecture/index.md +22 -0
  187. package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
  188. package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
  189. package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
  190. package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
  191. package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
  192. package/expertise/architecture/patterns/event-driven.md +797 -0
  193. package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
  194. package/expertise/architecture/patterns/index.md +27 -0
  195. package/expertise/architecture/patterns/layered-architecture.md +736 -0
  196. package/expertise/architecture/patterns/microservices.md +753 -0
  197. package/expertise/architecture/patterns/modular-monolith.md +692 -0
  198. package/expertise/architecture/patterns/monolith.md +626 -0
  199. package/expertise/architecture/patterns/plugin-architecture.md +735 -0
  200. package/expertise/architecture/patterns/serverless.md +780 -0
  201. package/expertise/architecture/scaling/database-scaling.md +615 -0
  202. package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
  203. package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
  204. package/expertise/architecture/scaling/index.md +24 -0
  205. package/expertise/architecture/scaling/multi-tenancy.md +800 -0
  206. package/expertise/architecture/scaling/stateless-design.md +787 -0
  207. package/expertise/backend/embedded-firmware.md +625 -0
  208. package/expertise/backend/go.md +853 -0
  209. package/expertise/backend/index.md +24 -0
  210. package/expertise/backend/java-spring.md +448 -0
  211. package/expertise/backend/node-typescript.md +625 -0
  212. package/expertise/backend/python-fastapi.md +724 -0
  213. package/expertise/backend/rust.md +458 -0
  214. package/expertise/backend/solidity.md +711 -0
  215. package/expertise/composition-map.yaml +443 -0
  216. package/expertise/content/foundations/content-modeling.md +395 -0
  217. package/expertise/content/foundations/editorial-standards.md +449 -0
  218. package/expertise/content/foundations/index.md +24 -0
  219. package/expertise/content/foundations/microcopy.md +455 -0
  220. package/expertise/content/foundations/terminology-governance.md +509 -0
  221. package/expertise/content/index.md +34 -0
  222. package/expertise/content/patterns/accessibility-copy.md +518 -0
  223. package/expertise/content/patterns/index.md +24 -0
  224. package/expertise/content/patterns/notification-content.md +433 -0
  225. package/expertise/content/patterns/sample-content.md +486 -0
  226. package/expertise/content/patterns/state-copy.md +439 -0
  227. package/expertise/design/PROGRESS.md +58 -0
  228. package/expertise/design/disciplines/dark-mode-theming.md +577 -0
  229. package/expertise/design/disciplines/design-systems.md +595 -0
  230. package/expertise/design/disciplines/index.md +25 -0
  231. package/expertise/design/disciplines/information-architecture.md +800 -0
  232. package/expertise/design/disciplines/interaction-design.md +788 -0
  233. package/expertise/design/disciplines/responsive-design.md +552 -0
  234. package/expertise/design/disciplines/usability-testing.md +516 -0
  235. package/expertise/design/disciplines/user-research.md +792 -0
  236. package/expertise/design/foundations/accessibility-design.md +796 -0
  237. package/expertise/design/foundations/color-theory.md +797 -0
  238. package/expertise/design/foundations/iconography.md +795 -0
  239. package/expertise/design/foundations/index.md +26 -0
  240. package/expertise/design/foundations/motion-and-animation.md +653 -0
  241. package/expertise/design/foundations/rtl-design.md +585 -0
  242. package/expertise/design/foundations/spacing-and-layout.md +607 -0
  243. package/expertise/design/foundations/typography.md +800 -0
  244. package/expertise/design/foundations/visual-hierarchy.md +761 -0
  245. package/expertise/design/index.md +32 -0
  246. package/expertise/design/patterns/authentication-flows.md +474 -0
  247. package/expertise/design/patterns/content-consumption.md +789 -0
  248. package/expertise/design/patterns/data-display.md +618 -0
  249. package/expertise/design/patterns/e-commerce.md +1494 -0
  250. package/expertise/design/patterns/feedback-and-states.md +642 -0
  251. package/expertise/design/patterns/forms-and-input.md +819 -0
  252. package/expertise/design/patterns/gamification.md +801 -0
  253. package/expertise/design/patterns/index.md +31 -0
  254. package/expertise/design/patterns/microinteractions.md +449 -0
  255. package/expertise/design/patterns/navigation.md +800 -0
  256. package/expertise/design/patterns/notifications.md +705 -0
  257. package/expertise/design/patterns/onboarding.md +700 -0
  258. package/expertise/design/patterns/search-and-filter.md +601 -0
  259. package/expertise/design/patterns/settings-and-preferences.md +768 -0
  260. package/expertise/design/patterns/social-and-community.md +748 -0
  261. package/expertise/design/platforms/desktop-native.md +612 -0
  262. package/expertise/design/platforms/index.md +25 -0
  263. package/expertise/design/platforms/mobile-android.md +825 -0
  264. package/expertise/design/platforms/mobile-cross-platform.md +983 -0
  265. package/expertise/design/platforms/mobile-ios.md +699 -0
  266. package/expertise/design/platforms/tablet.md +794 -0
  267. package/expertise/design/platforms/web-dashboard.md +790 -0
  268. package/expertise/design/platforms/web-responsive.md +550 -0
  269. package/expertise/design/psychology/behavioral-nudges.md +449 -0
  270. package/expertise/design/psychology/cognitive-load.md +1191 -0
  271. package/expertise/design/psychology/error-psychology.md +778 -0
  272. package/expertise/design/psychology/index.md +22 -0
  273. package/expertise/design/psychology/persuasive-design.md +736 -0
  274. package/expertise/design/psychology/user-mental-models.md +623 -0
  275. package/expertise/design/tooling/open-pencil.md +266 -0
  276. package/expertise/frontend/angular.md +1073 -0
  277. package/expertise/frontend/desktop-electron.md +546 -0
  278. package/expertise/frontend/flutter.md +782 -0
  279. package/expertise/frontend/index.md +27 -0
  280. package/expertise/frontend/native-android.md +409 -0
  281. package/expertise/frontend/native-ios.md +490 -0
  282. package/expertise/frontend/react-native.md +1160 -0
  283. package/expertise/frontend/react.md +808 -0
  284. package/expertise/frontend/vue.md +1089 -0
  285. package/expertise/humanize/domain-rules-code.md +79 -0
  286. package/expertise/humanize/domain-rules-content.md +67 -0
  287. package/expertise/humanize/domain-rules-technical-docs.md +56 -0
  288. package/expertise/humanize/index.md +35 -0
  289. package/expertise/humanize/self-audit-checklist.md +87 -0
  290. package/expertise/humanize/sentence-patterns.md +218 -0
  291. package/expertise/humanize/vocabulary-blacklist.md +105 -0
  292. package/expertise/i18n/PROGRESS.md +65 -0
  293. package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
  294. package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
  295. package/expertise/i18n/advanced/complex-scripts.md +30 -0
  296. package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
  297. package/expertise/i18n/advanced/testing-i18n.md +28 -0
  298. package/expertise/i18n/content/content-adaptation.md +23 -0
  299. package/expertise/i18n/content/locale-specific-formatting.md +23 -0
  300. package/expertise/i18n/content/machine-translation-integration.md +28 -0
  301. package/expertise/i18n/content/translation-management.md +29 -0
  302. package/expertise/i18n/foundations/date-time-calendars.md +67 -0
  303. package/expertise/i18n/foundations/i18n-architecture.md +272 -0
  304. package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
  305. package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
  306. package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
  307. package/expertise/i18n/foundations/string-externalization.md +236 -0
  308. package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
  309. package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
  310. package/expertise/i18n/index.md +38 -0
  311. package/expertise/i18n/platform/backend-i18n.md +31 -0
  312. package/expertise/i18n/platform/flutter-i18n.md +148 -0
  313. package/expertise/i18n/platform/native-android-i18n.md +36 -0
  314. package/expertise/i18n/platform/native-ios-i18n.md +36 -0
  315. package/expertise/i18n/platform/react-i18n.md +103 -0
  316. package/expertise/i18n/platform/web-css-i18n.md +81 -0
  317. package/expertise/i18n/rtl/arabic-specific.md +175 -0
  318. package/expertise/i18n/rtl/hebrew-specific.md +149 -0
  319. package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
  320. package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
  321. package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
  322. package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
  323. package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
  324. package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
  325. package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
  326. package/expertise/i18n/rtl/rtl-typography.md +160 -0
  327. package/expertise/index.md +113 -0
  328. package/expertise/index.yaml +216 -0
  329. package/expertise/infrastructure/cloud-aws.md +597 -0
  330. package/expertise/infrastructure/cloud-gcp.md +599 -0
  331. package/expertise/infrastructure/cybersecurity.md +816 -0
  332. package/expertise/infrastructure/database-mongodb.md +447 -0
  333. package/expertise/infrastructure/database-postgres.md +400 -0
  334. package/expertise/infrastructure/devops-cicd.md +787 -0
  335. package/expertise/infrastructure/index.md +27 -0
  336. package/expertise/performance/PROGRESS.md +50 -0
  337. package/expertise/performance/backend/api-latency.md +1204 -0
  338. package/expertise/performance/backend/background-jobs.md +506 -0
  339. package/expertise/performance/backend/connection-pooling.md +1209 -0
  340. package/expertise/performance/backend/database-query-optimization.md +515 -0
  341. package/expertise/performance/backend/index.md +23 -0
  342. package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
  343. package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
  344. package/expertise/performance/foundations/caching-strategies.md +489 -0
  345. package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
  346. package/expertise/performance/foundations/index.md +24 -0
  347. package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
  348. package/expertise/performance/foundations/memory-management.md +964 -0
  349. package/expertise/performance/foundations/performance-budgets.md +1314 -0
  350. package/expertise/performance/index.md +31 -0
  351. package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
  352. package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
  353. package/expertise/performance/infrastructure/index.md +22 -0
  354. package/expertise/performance/infrastructure/load-balancing.md +1081 -0
  355. package/expertise/performance/infrastructure/observability.md +1079 -0
  356. package/expertise/performance/mobile/index.md +23 -0
  357. package/expertise/performance/mobile/mobile-animations.md +544 -0
  358. package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
  359. package/expertise/performance/mobile/mobile-network.md +452 -0
  360. package/expertise/performance/mobile/mobile-rendering.md +599 -0
  361. package/expertise/performance/mobile/mobile-startup-time.md +505 -0
  362. package/expertise/performance/platform-specific/flutter-performance.md +647 -0
  363. package/expertise/performance/platform-specific/index.md +22 -0
  364. package/expertise/performance/platform-specific/node-performance.md +1307 -0
  365. package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
  366. package/expertise/performance/platform-specific/react-performance.md +1403 -0
  367. package/expertise/performance/web/bundle-optimization.md +1239 -0
  368. package/expertise/performance/web/image-and-media.md +636 -0
  369. package/expertise/performance/web/index.md +24 -0
  370. package/expertise/performance/web/network-optimization.md +1133 -0
  371. package/expertise/performance/web/rendering-performance.md +1098 -0
  372. package/expertise/performance/web/ssr-and-hydration.md +918 -0
  373. package/expertise/performance/web/web-vitals.md +1374 -0
  374. package/expertise/quality/accessibility.md +985 -0
  375. package/expertise/quality/evidence-based-verification.md +499 -0
  376. package/expertise/quality/index.md +24 -0
  377. package/expertise/quality/ml-model-audit.md +614 -0
  378. package/expertise/quality/performance.md +600 -0
  379. package/expertise/quality/testing-api.md +891 -0
  380. package/expertise/quality/testing-mobile.md +496 -0
  381. package/expertise/quality/testing-web.md +849 -0
  382. package/expertise/security/PROGRESS.md +54 -0
  383. package/expertise/security/agentic-identity.md +540 -0
  384. package/expertise/security/compliance-frameworks.md +601 -0
  385. package/expertise/security/data/data-encryption.md +364 -0
  386. package/expertise/security/data/data-privacy-gdpr.md +692 -0
  387. package/expertise/security/data/database-security.md +1171 -0
  388. package/expertise/security/data/index.md +22 -0
  389. package/expertise/security/data/pii-handling.md +531 -0
  390. package/expertise/security/foundations/authentication.md +1041 -0
  391. package/expertise/security/foundations/authorization.md +603 -0
  392. package/expertise/security/foundations/cryptography.md +1001 -0
  393. package/expertise/security/foundations/index.md +25 -0
  394. package/expertise/security/foundations/owasp-top-10.md +1354 -0
  395. package/expertise/security/foundations/secrets-management.md +1217 -0
  396. package/expertise/security/foundations/secure-sdlc.md +700 -0
  397. package/expertise/security/foundations/supply-chain-security.md +698 -0
  398. package/expertise/security/index.md +31 -0
  399. package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
  400. package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
  401. package/expertise/security/infrastructure/container-security.md +721 -0
  402. package/expertise/security/infrastructure/incident-response.md +1295 -0
  403. package/expertise/security/infrastructure/index.md +24 -0
  404. package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
  405. package/expertise/security/infrastructure/network-security.md +1337 -0
  406. package/expertise/security/mobile/index.md +23 -0
  407. package/expertise/security/mobile/mobile-android-security.md +1218 -0
  408. package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
  409. package/expertise/security/mobile/mobile-data-storage.md +1265 -0
  410. package/expertise/security/mobile/mobile-ios-security.md +1401 -0
  411. package/expertise/security/mobile/mobile-network-security.md +1520 -0
  412. package/expertise/security/smart-contract-security.md +594 -0
  413. package/expertise/security/testing/index.md +22 -0
  414. package/expertise/security/testing/penetration-testing.md +1258 -0
  415. package/expertise/security/testing/security-code-review.md +1765 -0
  416. package/expertise/security/testing/threat-modeling.md +1074 -0
  417. package/expertise/security/testing/vulnerability-scanning.md +1062 -0
  418. package/expertise/security/web/api-security.md +586 -0
  419. package/expertise/security/web/cors-and-headers.md +433 -0
  420. package/expertise/security/web/csrf.md +562 -0
  421. package/expertise/security/web/file-upload.md +1477 -0
  422. package/expertise/security/web/index.md +25 -0
  423. package/expertise/security/web/injection.md +1375 -0
  424. package/expertise/security/web/session-management.md +1101 -0
  425. package/expertise/security/web/xss.md +1158 -0
  426. package/exports/README.md +17 -0
  427. package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
  428. package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
  429. package/exports/hosts/claude/.claude/agents/designer.md +55 -0
  430. package/exports/hosts/claude/.claude/agents/executor.md +55 -0
  431. package/exports/hosts/claude/.claude/agents/learner.md +51 -0
  432. package/exports/hosts/claude/.claude/agents/planner.md +53 -0
  433. package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
  434. package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
  435. package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
  436. package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
  437. package/exports/hosts/claude/.claude/commands/author.md +42 -0
  438. package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
  439. package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
  440. package/exports/hosts/claude/.claude/commands/design.md +44 -0
  441. package/exports/hosts/claude/.claude/commands/discover.md +37 -0
  442. package/exports/hosts/claude/.claude/commands/execute.md +48 -0
  443. package/exports/hosts/claude/.claude/commands/learn.md +38 -0
  444. package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
  445. package/exports/hosts/claude/.claude/commands/plan.md +39 -0
  446. package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
  447. package/exports/hosts/claude/.claude/commands/review.md +40 -0
  448. package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
  449. package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
  450. package/exports/hosts/claude/.claude/commands/specify.md +38 -0
  451. package/exports/hosts/claude/.claude/commands/verify.md +37 -0
  452. package/exports/hosts/claude/.claude/settings.json +34 -0
  453. package/exports/hosts/claude/CLAUDE.md +19 -0
  454. package/exports/hosts/claude/export.manifest.json +38 -0
  455. package/exports/hosts/claude/host-package.json +67 -0
  456. package/exports/hosts/codex/AGENTS.md +19 -0
  457. package/exports/hosts/codex/export.manifest.json +38 -0
  458. package/exports/hosts/codex/host-package.json +41 -0
  459. package/exports/hosts/cursor/.cursor/hooks.json +16 -0
  460. package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
  461. package/exports/hosts/cursor/export.manifest.json +38 -0
  462. package/exports/hosts/cursor/host-package.json +42 -0
  463. package/exports/hosts/gemini/GEMINI.md +19 -0
  464. package/exports/hosts/gemini/export.manifest.json +38 -0
  465. package/exports/hosts/gemini/host-package.json +41 -0
  466. package/hooks/README.md +18 -0
  467. package/hooks/definitions/loop_cap_guard.yaml +21 -0
  468. package/hooks/definitions/post_tool_capture.yaml +24 -0
  469. package/hooks/definitions/pre_compact_summary.yaml +19 -0
  470. package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
  471. package/hooks/definitions/protected_path_write_guard.yaml +19 -0
  472. package/hooks/definitions/session_start.yaml +19 -0
  473. package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
  474. package/hooks/loop-cap-guard +17 -0
  475. package/hooks/post-tool-lint +36 -0
  476. package/hooks/protected-path-write-guard +17 -0
  477. package/hooks/session-start +41 -0
  478. package/llms-full.txt +2355 -0
  479. package/llms.txt +43 -0
  480. package/package.json +79 -0
  481. package/roles/README.md +20 -0
  482. package/roles/clarifier.md +42 -0
  483. package/roles/content-author.md +63 -0
  484. package/roles/designer.md +55 -0
  485. package/roles/executor.md +55 -0
  486. package/roles/learner.md +51 -0
  487. package/roles/planner.md +53 -0
  488. package/roles/researcher.md +43 -0
  489. package/roles/reviewer.md +54 -0
  490. package/roles/specifier.md +47 -0
  491. package/roles/verifier.md +71 -0
  492. package/schemas/README.md +24 -0
  493. package/schemas/accepted-learning.schema.json +20 -0
  494. package/schemas/author-artifact.schema.json +156 -0
  495. package/schemas/clarification.schema.json +19 -0
  496. package/schemas/design-artifact.schema.json +80 -0
  497. package/schemas/docs-claim.schema.json +18 -0
  498. package/schemas/export-manifest.schema.json +20 -0
  499. package/schemas/hook.schema.json +67 -0
  500. package/schemas/host-export-package.schema.json +18 -0
  501. package/schemas/implementation-plan.schema.json +19 -0
  502. package/schemas/proposed-learning.schema.json +19 -0
  503. package/schemas/research.schema.json +18 -0
  504. package/schemas/review.schema.json +29 -0
  505. package/schemas/run-manifest.schema.json +18 -0
  506. package/schemas/spec-challenge.schema.json +18 -0
  507. package/schemas/spec.schema.json +20 -0
  508. package/schemas/usage.schema.json +102 -0
  509. package/schemas/verification-proof.schema.json +29 -0
  510. package/schemas/wazir-manifest.schema.json +173 -0
  511. package/skills/README.md +40 -0
  512. package/skills/brainstorming/SKILL.md +77 -0
  513. package/skills/debugging/SKILL.md +50 -0
  514. package/skills/design/SKILL.md +61 -0
  515. package/skills/dispatching-parallel-agents/SKILL.md +128 -0
  516. package/skills/executing-plans/SKILL.md +70 -0
  517. package/skills/finishing-a-development-branch/SKILL.md +169 -0
  518. package/skills/humanize/SKILL.md +123 -0
  519. package/skills/init-pipeline/SKILL.md +124 -0
  520. package/skills/prepare-next/SKILL.md +20 -0
  521. package/skills/receiving-code-review/SKILL.md +123 -0
  522. package/skills/requesting-code-review/SKILL.md +105 -0
  523. package/skills/requesting-code-review/code-reviewer.md +108 -0
  524. package/skills/run-audit/SKILL.md +197 -0
  525. package/skills/scan-project/SKILL.md +41 -0
  526. package/skills/self-audit/SKILL.md +153 -0
  527. package/skills/subagent-driven-development/SKILL.md +154 -0
  528. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
  529. package/skills/subagent-driven-development/implementer-prompt.md +102 -0
  530. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  531. package/skills/tdd/SKILL.md +23 -0
  532. package/skills/using-git-worktrees/SKILL.md +163 -0
  533. package/skills/using-skills/SKILL.md +95 -0
  534. package/skills/verification/SKILL.md +22 -0
  535. package/skills/wazir/SKILL.md +463 -0
  536. package/skills/writing-plans/SKILL.md +30 -0
  537. package/skills/writing-skills/SKILL.md +157 -0
  538. package/skills/writing-skills/anthropic-best-practices.md +122 -0
  539. package/skills/writing-skills/persuasion-principles.md +50 -0
  540. package/templates/README.md +20 -0
  541. package/templates/artifacts/README.md +10 -0
  542. package/templates/artifacts/accepted-learning.md +19 -0
  543. package/templates/artifacts/accepted-learning.template.json +12 -0
  544. package/templates/artifacts/author.md +74 -0
  545. package/templates/artifacts/author.template.json +19 -0
  546. package/templates/artifacts/clarification.md +21 -0
  547. package/templates/artifacts/clarification.template.json +12 -0
  548. package/templates/artifacts/execute-notes.md +19 -0
  549. package/templates/artifacts/implementation-plan.md +21 -0
  550. package/templates/artifacts/implementation-plan.template.json +11 -0
  551. package/templates/artifacts/learning-proposal.md +19 -0
  552. package/templates/artifacts/next-run-handoff.md +21 -0
  553. package/templates/artifacts/plan-review.md +19 -0
  554. package/templates/artifacts/proposed-learning.template.json +12 -0
  555. package/templates/artifacts/research.md +21 -0
  556. package/templates/artifacts/research.template.json +12 -0
  557. package/templates/artifacts/review-findings.md +19 -0
  558. package/templates/artifacts/review.template.json +11 -0
  559. package/templates/artifacts/run-manifest.template.json +8 -0
  560. package/templates/artifacts/spec-challenge.md +19 -0
  561. package/templates/artifacts/spec-challenge.template.json +11 -0
  562. package/templates/artifacts/spec.md +21 -0
  563. package/templates/artifacts/spec.template.json +12 -0
  564. package/templates/artifacts/verification-proof.md +19 -0
  565. package/templates/artifacts/verification-proof.template.json +11 -0
  566. package/templates/examples/accepted-learning.example.json +14 -0
  567. package/templates/examples/author.example.json +152 -0
  568. package/templates/examples/clarification.example.json +15 -0
  569. package/templates/examples/docs-claim.example.json +8 -0
  570. package/templates/examples/export-manifest.example.json +7 -0
  571. package/templates/examples/host-export-package.example.json +11 -0
  572. package/templates/examples/implementation-plan.example.json +17 -0
  573. package/templates/examples/proposed-learning.example.json +13 -0
  574. package/templates/examples/research.example.json +15 -0
  575. package/templates/examples/research.example.md +6 -0
  576. package/templates/examples/review.example.json +17 -0
  577. package/templates/examples/run-manifest.example.json +9 -0
  578. package/templates/examples/spec-challenge.example.json +14 -0
  579. package/templates/examples/spec.example.json +21 -0
  580. package/templates/examples/verification-proof.example.json +21 -0
  581. package/templates/examples/wazir-manifest.example.yaml +65 -0
  582. package/templates/task-definition-schema.md +99 -0
  583. package/tooling/README.md +20 -0
  584. package/tooling/src/adapters/context-mode.js +50 -0
  585. package/tooling/src/capture/command.js +376 -0
  586. package/tooling/src/capture/store.js +99 -0
  587. package/tooling/src/capture/usage.js +270 -0
  588. package/tooling/src/checks/branches.js +50 -0
  589. package/tooling/src/checks/brand-truth.js +110 -0
  590. package/tooling/src/checks/changelog.js +231 -0
  591. package/tooling/src/checks/command-registry.js +36 -0
  592. package/tooling/src/checks/commits.js +102 -0
  593. package/tooling/src/checks/docs-drift.js +103 -0
  594. package/tooling/src/checks/docs-truth.js +201 -0
  595. package/tooling/src/checks/runtime-surface.js +156 -0
  596. package/tooling/src/cli.js +116 -0
  597. package/tooling/src/command-options.js +56 -0
  598. package/tooling/src/commands/validate.js +320 -0
  599. package/tooling/src/doctor/command.js +91 -0
  600. package/tooling/src/export/command.js +77 -0
  601. package/tooling/src/export/compiler.js +498 -0
  602. package/tooling/src/guards/loop-cap-guard.js +52 -0
  603. package/tooling/src/guards/protected-path-write-guard.js +67 -0
  604. package/tooling/src/index/command.js +152 -0
  605. package/tooling/src/index/storage.js +1061 -0
  606. package/tooling/src/index/summarizers.js +261 -0
  607. package/tooling/src/loaders.js +18 -0
  608. package/tooling/src/project-root.js +22 -0
  609. package/tooling/src/recall/command.js +225 -0
  610. package/tooling/src/schema-validator.js +30 -0
  611. package/tooling/src/state-root.js +40 -0
  612. package/tooling/src/status/command.js +71 -0
  613. package/wazir.manifest.yaml +135 -0
  614. package/workflows/README.md +19 -0
  615. package/workflows/author.md +42 -0
  616. package/workflows/clarify.md +38 -0
  617. package/workflows/design-review.md +46 -0
  618. package/workflows/design.md +44 -0
  619. package/workflows/discover.md +37 -0
  620. package/workflows/execute.md +48 -0
  621. package/workflows/learn.md +38 -0
  622. package/workflows/plan-review.md +42 -0
  623. package/workflows/plan.md +39 -0
  624. package/workflows/prepare-next.md +37 -0
  625. package/workflows/review.md +40 -0
  626. package/workflows/run-audit.md +41 -0
  627. package/workflows/spec-challenge.md +41 -0
  628. package/workflows/specify.md +38 -0
  629. package/workflows/verify.md +37 -0
@@ -0,0 +1,1360 @@
1
+ # Error Handling Anti-Patterns
2
+
3
+ **Module:** Code Anti-Patterns / Error Handling
4
+ **Severity range:** Low to Critical
5
+ **Applies to:** All languages with exception/error mechanisms
6
+ **Prerequisites:** Basic understanding of try/catch, async patterns, typed error systems
7
+
8
+ Error handling code is the least tested, least reviewed, and most dangerous code in any system.
9
+ A 2014 University of Toronto study of Cassandra, HBase, HDFS, MapReduce, and Redis found that
10
+ 92% of catastrophic failures were caused by incorrect handling of non-fatal errors explicitly
11
+ signalled in software. In 35% of those cases, the error handler was empty, only contained a log
12
+ statement, or had clearly incomplete logic. These are not exotic edge cases -- they are trivial
13
+ mistakes that pass code review because error handling is treated as an afterthought. This module
14
+ catalogs 18 recurring anti-patterns, each with detection heuristics, real-world incident data,
15
+ and concrete fixes.
16
+
17
+ ---
18
+
19
+ ## Anti-Pattern Catalog
20
+
21
+ ### AP-01: Pokemon Exception Handling
22
+
23
+ **Also known as:** Catch 'Em All, Diaper Pattern, Catch-All
24
+ **Frequency:** Very Common
25
+ **Severity:** Critical
26
+ **Detection difficulty:** Easy
27
+
28
+ **What it looks like:**
29
+
30
+ ```python
31
+ # Python
32
+ try:
33
+ process_order(order)
34
+ except Exception:
35
+ pass
36
+
37
+ # Java
38
+ try {
39
+ processOrder(order);
40
+ } catch (Exception e) {
41
+ // handle error
42
+ }
43
+
44
+ # JavaScript
45
+ try {
46
+ processOrder(order);
47
+ } catch (e) {
48
+ console.log("something went wrong");
49
+ }
50
+ ```
51
+
52
+ **Why developers do it:**
53
+
54
+ Quick fix during development to "get it working." Often starts as a placeholder that survives to production. Developers also use it defensively when they do not know which exceptions a third-party library can throw. The CWE (Common Weakness Enumeration) lists this as record #397.
55
+
56
+ **What goes wrong:**
57
+
58
+ The handler catches `NameError`, `TypeError`, `KeyboardInterrupt`, `SystemExit`, and everything else indiscriminately. A misspelled variable name becomes indistinguishable from a network timeout. The University of Toronto study found this pattern directly contributed to catastrophic failures in distributed data stores -- the error handler swallowed a real failure signal, and the system continued operating on corrupted state.
59
+
60
+ In one documented case, an `undefined` variable raised a `NameError` inside a Pokemon catch block. The function returned `None` silently, causing downstream data corruption that was only discovered days later when customers reported incorrect billing amounts.
61
+
62
+ **The fix:**
63
+
64
+ ```python
65
+ # Before: catches everything including SystemExit and KeyboardInterrupt
66
+ try:
67
+ result = external_api.fetch(order_id)
68
+ except Exception:
69
+ pass
70
+
71
+ # After: catch specific, actionable exceptions
72
+ try:
73
+ result = external_api.fetch(order_id)
74
+ except ConnectionTimeout:
75
+ result = cache.get_stale(order_id)
76
+ metrics.increment("api.timeout.fallback")
77
+ except ValidationError as e:
78
+ logger.warning("Invalid order %s: %s", order_id, e)
79
+ raise
80
+ ```
81
+
82
+ **Detection rule:**
83
+
84
+ Flag any `catch(Exception)`, `catch(...)`, `except Exception`, or bare `except:` that does not re-raise. Lint rules: `pylint broad-except`, `SonarQube S2221`, `ESLint no-useless-catch`.
85
+
86
+ ---
87
+
88
+ ### AP-02: The Silent Swallow
89
+
90
+ **Also known as:** Exception Hiding, Error Swallowing, Empty Catch
91
+ **Frequency:** Very Common
92
+ **Severity:** Critical
93
+ **Detection difficulty:** Moderate
94
+
95
+ **What it looks like:**
96
+
97
+ ```java
98
+ try {
99
+ db.executeUpdate(sql);
100
+ } catch (SQLException e) {
101
+ // TODO: handle this later
102
+ }
103
+
104
+ try {
105
+ sendNotification(user);
106
+ } catch (Exception e) {
107
+ // not critical, ignore
108
+ }
109
+ ```
110
+
111
+ ```javascript
112
+ try {
113
+ await saveToDatabase(record);
114
+ } catch (err) {
115
+ // swallow
116
+ }
117
+ ```
118
+
119
+ **Why developers do it:**
120
+
121
+ The developer believes the exception is non-critical ("it's just a notification") or plans to handle it later. Wikipedia documents this as "error hiding" -- the practice of catching an error and continuing without logging, processing, or reporting it.
122
+
123
+ **What goes wrong:**
124
+
125
+ Information about the error is permanently lost. Depending on the system, this can cause unintended side effects that cascade into other errors. The n8n workflow automation platform had a documented bug (Issue #19434) where a URL constructor threw an error inside a Code node. The try-catch swallowed it and returned an empty string. The real issue -- missing `URL` constructor in the sandboxed environment -- was invisible. Users saw only mysterious data-processing failures.
126
+
127
+ Harness.io reported that swallowed exceptions are a major factor causing production errors to go unnoticed, particularly hiding database rollback failures, file I/O errors, and network timeouts.
128
+
129
+ **The fix:**
130
+
131
+ ```java
132
+ // Before
133
+ try {
134
+ db.executeUpdate(sql);
135
+ } catch (SQLException e) {}
136
+
137
+ // After: at minimum, log. Better: propagate or handle.
138
+ try {
139
+ db.executeUpdate(sql);
140
+ } catch (SQLException e) {
141
+ logger.error("Failed to execute update: {}", sql, e);
142
+ throw new DataAccessException("Update failed for query", e);
143
+ }
144
+ ```
145
+
146
+ If the exception genuinely can be ignored (e.g., best-effort cache write), document why explicitly:
147
+
148
+ ```java
149
+ try {
150
+ cache.put(key, value);
151
+ } catch (CacheException e) {
152
+ // Intentionally ignored: cache miss is acceptable, DB is source of truth.
153
+ // Metric tracked separately via cache health monitor.
154
+ metrics.increment("cache.write.failure");
155
+ }
156
+ ```
157
+
158
+ **Detection rule:**
159
+
160
+ Flag empty catch blocks and catch blocks containing only comments or TODO markers. Lint rules: `SonarQube S108`, `ESLint no-empty`, `clang-tidy bugprone-empty-catch`, `Checkstyle EmptyCatchBlock`.
161
+
162
+ ---
163
+
164
+ ### AP-03: Exceptions as Flow Control
165
+
166
+ **Also known as:** Conditional Exceptions, Exception-Driven Logic, Vexing Exceptions
167
+ **Frequency:** Common
168
+ **Severity:** Medium
169
+ **Detection difficulty:** Moderate
170
+
171
+ **What it looks like:**
172
+
173
+ ```python
174
+ # Using exception to check if user exists
175
+ def get_user(user_id):
176
+ try:
177
+ return db.query(f"SELECT * FROM users WHERE id = {user_id}")
178
+ except UserNotFoundError:
179
+ return create_default_user(user_id)
180
+
181
+ # Using exception for type checking
182
+ def parse_input(value):
183
+ try:
184
+ return int(value)
185
+ except ValueError:
186
+ try:
187
+ return float(value)
188
+ except ValueError:
189
+ return value
190
+ ```
191
+
192
+ ```csharp
193
+ // C# classic: using Parse + catch instead of TryParse
194
+ int age;
195
+ try {
196
+ age = int.Parse(userInput);
197
+ } catch (FormatException) {
198
+ age = 0;
199
+ }
200
+ ```
201
+
202
+ **Why developers do it:**
203
+
204
+ It feels concise. In Python, "easier to ask forgiveness than permission" (EAFP) is sometimes cited as justification, but EAFP applies to race-condition avoidance, not routine control flow.
205
+
206
+ **What goes wrong:**
207
+
208
+ Joshua Bloch demonstrated in Effective Java that exception-based looping is roughly 2x slower than conditional checks because the JVM must capture the entire call stack on every throw. Microsoft's performance documentation explicitly labels this a "Performance Sin." Beyond speed, it obscures intent -- a reader cannot tell whether the exception path is the error case or the expected case.
209
+
210
+ The Databricks SDK for Python (Issue #1117) documented how inconsistent exception handling forced users into control-flow anti-patterns, checking HTTP status by catching exceptions rather than inspecting return values.
211
+
212
+ **The fix:**
213
+
214
+ ```csharp
215
+ // Before: exception as flow control
216
+ int age;
217
+ try {
218
+ age = int.Parse(userInput);
219
+ } catch (FormatException) {
220
+ age = 0;
221
+ }
222
+
223
+ // After: use TryParse / conditional check
224
+ int age = int.TryParse(userInput, out var parsed) ? parsed : 0;
225
+ ```
226
+
227
+ ```python
228
+ # Before
229
+ try:
230
+ value = my_dict[key]
231
+ except KeyError:
232
+ value = default
233
+
234
+ # After
235
+ value = my_dict.get(key, default)
236
+ ```
237
+
238
+ **Detection rule:**
239
+
240
+ Flag catch blocks where the exception type represents a predictable, non-exceptional condition (e.g., `KeyError`, `FormatException`, `NumberFormatException`) and where the catch body sets a default value. High ratio of caught-to-uncaught exceptions in production telemetry is a signal.
241
+
242
+ ---
243
+
244
+ ### AP-04: Null as Error Signal
245
+
246
+ **Also known as:** The Billion-Dollar Mistake, Null Return Pattern, Silent Null
247
+ **Frequency:** Very Common
248
+ **Severity:** High
249
+ **Detection difficulty:** Hard
250
+
251
+ **What it looks like:**
252
+
253
+ ```java
254
+ public User findUser(String id) {
255
+ try {
256
+ return userRepo.findById(id);
257
+ } catch (DatabaseException e) {
258
+ return null; // caller has no idea why
259
+ }
260
+ }
261
+
262
+ // Caller side -- the NullPointerException lottery
263
+ User user = findUser(id);
264
+ String name = user.getName(); // NPE if user is null
265
+ ```
266
+
267
+ ```javascript
268
+ function getConfig(key) {
269
+ const val = configStore[key];
270
+ if (!val) return null;
271
+ return val;
272
+ }
273
+ // Caller forgets null check -> TypeError: Cannot read property of null
274
+ ```
275
+
276
+ **Why developers do it:**
277
+
278
+ It avoids throwing, which feels "simpler." The method signature stays clean. Tony Hoare, inventor of the null reference, called it his "billion-dollar mistake" at QCon London 2009, stating: "It has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."
279
+
280
+ **What goes wrong:**
281
+
282
+ The null propagates through the system until it detonates far from the original error site. Debugging becomes a search through call chains to find where null was introduced. Every caller must defensively null-check, and inevitably one does not. The original error context (why the lookup failed) is permanently lost.
283
+
284
+ **The fix:**
285
+
286
+ ```java
287
+ // Before
288
+ public User findUser(String id) {
289
+ try {
290
+ return userRepo.findById(id);
291
+ } catch (DatabaseException e) {
292
+ return null;
293
+ }
294
+ }
295
+
296
+ // After: use Optional (Java), Result type (Rust), or throw
297
+ public Optional<User> findUser(String id) {
298
+ return userRepo.findOptionalById(id);
299
+ }
300
+
301
+ // Or throw with context
302
+ public User findUser(String id) throws UserNotFoundException {
303
+ return userRepo.findById(id)
304
+ .orElseThrow(() -> new UserNotFoundException(id));
305
+ }
306
+ ```
307
+
308
+ ```typescript
309
+ // TypeScript: use strict null checks + union types
310
+ function getConfig(key: string): ConfigValue | undefined {
311
+ return configStore.get(key);
312
+ }
313
+ ```
314
+
315
+ **Detection rule:**
316
+
317
+ Flag methods that catch exceptions and return null. Flag methods returning null without `@Nullable` annotation. Enable `-strictNullChecks` in TypeScript, `Optional` enforcement in Java. Lint: `SonarQube S2637`, `NullAway`.
318
+
319
+ ---
320
+
321
+ ### AP-05: Log and Rethrow
322
+
323
+ **Also known as:** Double Logging, Log-and-Throw, Catch-Log-Rethrow
324
+ **Frequency:** Common
325
+ **Severity:** Medium
326
+ **Detection difficulty:** Easy
327
+
328
+ **What it looks like:**
329
+
330
+ ```java
331
+ try {
332
+ processPayment(order);
333
+ } catch (PaymentException e) {
334
+ logger.error("Payment failed", e);
335
+ throw e; // same exception logged again at next catch
336
+ }
337
+
338
+ // Three layers up:
339
+ try {
340
+ handleOrder(order);
341
+ } catch (PaymentException e) {
342
+ logger.error("Order processing failed", e); // same stack trace, third time
343
+ throw new OrderException("Order failed", e);
344
+ }
345
+ ```
346
+
347
+ **Why developers do it:**
348
+
349
+ Each layer wants to "make sure" the error is logged. Developers do not trust that higher layers will log the exception. The TheServerSide documented this as one of the most common Java exception anti-patterns.
350
+
351
+ **What goes wrong:**
352
+
353
+ The same stack trace appears 3-5 times in logs, each with different context text. During an incident, an engineer searching for the root cause finds dozens of duplicate log entries, making it harder to identify the actual first occurrence. Rolf Engelhard described the result: "a log file that contains every stacktrace in a dozen repetitions and variations -- a nightmare when you try to understand what is going on." SonarQube rule S2139 specifically targets this pattern.
354
+
355
+ **The fix:**
356
+
357
+ Either log OR rethrow. Never both.
358
+
359
+ ```java
360
+ // Option A: Add context and rethrow (preferred in library code)
361
+ try {
362
+ processPayment(order);
363
+ } catch (PaymentException e) {
364
+ throw new OrderException("Payment failed for order " + order.getId(), e);
365
+ }
366
+
367
+ // Option B: Log and handle (preferred at boundary/top level)
368
+ try {
369
+ processPayment(order);
370
+ } catch (PaymentException e) {
371
+ logger.error("Payment failed for order {}: {}", order.getId(), e.getMessage(), e);
372
+ return PaymentResult.failed(e.getMessage());
373
+ }
374
+ ```
375
+
376
+ **Detection rule:**
377
+
378
+ Flag catch blocks that contain both a `logger.error()` call and a `throw` statement. Lint: `SonarQube S2139`, `PMD LoggerAndThrow`, Palantir baseline-error-prone `LogAndThrow`.
379
+
380
+ ---
381
+
382
+ ### AP-06: Catching the Base Error Class
383
+
384
+ **Also known as:** Catching Throwable, Catching BaseException, Nuclear Catch
385
+ **Frequency:** Common
386
+ **Severity:** Critical
387
+ **Detection difficulty:** Easy
388
+
389
+ **What it looks like:**
390
+
391
+ ```java
392
+ try {
393
+ processData(input);
394
+ } catch (Throwable t) {
395
+ logger.error("Error processing data", t);
396
+ return defaultResult();
397
+ }
398
+ ```
399
+
400
+ ```python
401
+ try:
402
+ process_data(input)
403
+ except BaseException:
404
+ return default_result()
405
+ ```
406
+
407
+ **Why developers do it:**
408
+
409
+ "I want to catch absolutely everything so the system never crashes." It feels like defensive programming.
410
+
411
+ **What goes wrong:**
412
+
413
+ In Java, `Throwable` includes `OutOfMemoryError`, `StackOverflowError`, and `ThreadDeath`. Catching these prevents the JVM from properly reporting fatal conditions. An `OutOfMemoryError` caught and "handled" by returning a default value leaves the JVM in an unstable state -- subsequent allocations may fail unpredictably, and the application limps along corrupting data instead of failing fast.
414
+
415
+ In Python, catching `BaseException` also catches `SystemExit` and `KeyboardInterrupt`, meaning Ctrl+C no longer works and `sys.exit()` calls are silently ignored. Baeldung documented this as a definitive bad practice: "Throwable is the superclass of all exceptions and errors. Catching it will intercept serious errors that the application cannot or should not handle."
416
+
417
+ **The fix:**
418
+
419
+ ```java
420
+ // Before
421
+ try {
422
+ processData(input);
423
+ } catch (Throwable t) {
424
+ return defaultResult();
425
+ }
426
+
427
+ // After: catch only recoverable exceptions
428
+ try {
429
+ processData(input);
430
+ } catch (ProcessingException | IOException e) {
431
+ logger.error("Data processing failed", e);
432
+ return defaultResult();
433
+ }
434
+ // Let OutOfMemoryError, StackOverflowError propagate and crash the process
435
+ ```
436
+
437
+ **Detection rule:**
438
+
439
+ Flag `catch(Throwable)`, `catch(Error)` in Java; `except BaseException` in Python; `catch {}` without type in Swift. Lint: `SonarQube S1181`, `Checkstyle IllegalCatch`, `PMD AvoidCatchingThrowable`.
440
+
441
+ ---
442
+
443
+ ### AP-07: Generic Error Messages
444
+
445
+ **Also known as:** "Something Went Wrong" Syndrome, Unhelpful Error, Context-Free Error
446
+ **Frequency:** Very Common
447
+ **Severity:** High
448
+ **Detection difficulty:** Moderate
449
+
450
+ **What it looks like:**
451
+
452
+ ```javascript
453
+ try {
454
+ await deployService(config);
455
+ } catch (err) {
456
+ throw new Error("Deployment failed");
457
+ // Original error: "EACCES: permission denied, open '/etc/nginx/conf.d/app.conf'"
458
+ // What the on-call engineer sees: "Deployment failed"
459
+ }
460
+ ```
461
+
462
+ ```python
463
+ except DatabaseError as e:
464
+ raise AppError("An error occurred while processing your request")
465
+ ```
466
+
467
+ **Why developers do it:**
468
+
469
+ Security guidance says "don't expose internals to users." Developers apply this rule everywhere, including internal logs and error chains, stripping context that only engineers would see.
470
+
471
+ **What goes wrong:**
472
+
473
+ The on-call engineer sees "Deployment failed" in the alert. They have no idea if it is a permission error, a network error, a config syntax error, or a disk space issue. Triage time increases from minutes to hours. The security concern about user-facing messages is valid, but internal error chains and server-side logs need full context.
474
+
475
+ CQR's security research acknowledges the tension: user-facing errors should be generic, but server-side logs must contain the full error chain with stack trace and contextual data, accessible only to authorized personnel.
476
+
477
+ **The fix:**
478
+
479
+ Separate user-facing messages from internal error context:
480
+
481
+ ```python
482
+ # Before
483
+ except DatabaseError as e:
484
+ raise AppError("An error occurred")
485
+
486
+ # After: preserve context internally, sanitize externally
487
+ except DatabaseError as e:
488
+ logger.error("DB query failed", extra={
489
+ "query": query_name,
490
+ "table": table,
491
+ "original_error": str(e),
492
+ })
493
+ raise AppError(
494
+ user_message="We're having trouble processing your request. Please try again.",
495
+ internal_message=f"DatabaseError in {query_name} on {table}: {e}",
496
+ original=e,
497
+ )
498
+ ```
499
+
500
+ **Detection rule:**
501
+
502
+ Flag `throw new Error(string_literal)` where the literal contains no variable interpolation. Flag catch blocks that discard the original exception's message. Custom lint rule: error constructors must include either the original error or at least one variable.
503
+
504
+ ---
505
+
506
+ ### AP-08: Rethrowing Without Context
507
+
508
+ **Also known as:** Naked Rethrow, Context-Free Propagation, Blame Laundering
509
+ **Frequency:** Common
510
+ **Severity:** Medium
511
+ **Detection difficulty:** Moderate
512
+
513
+ **What it looks like:**
514
+
515
+ ```java
516
+ try {
517
+ loadConfig(path);
518
+ } catch (IOException e) {
519
+ throw new ConfigException(e.getMessage());
520
+ // Lost: the original stack trace, the exception chain
521
+ }
522
+ ```
523
+
524
+ ```python
525
+ try:
526
+ parse_config(path)
527
+ except yaml.YAMLError as e:
528
+ raise ConfigError(str(e)) # original traceback gone
529
+ ```
530
+
531
+ **Why developers do it:**
532
+
533
+ They want to translate the exception to a domain-specific type but forget to chain the cause. In Python, using `raise X` inside a catch without `from e` discards the original traceback.
534
+
535
+ **What goes wrong:**
536
+
537
+ The stack trace in the new exception starts at the rethrow point, not at the original failure. Debugging now requires guessing what happened before the rethrow. In large systems, this creates "stack trace gaps" where the most useful frames are missing.
538
+
539
+ **The fix:**
540
+
541
+ ```java
542
+ // Before: breaks the chain
543
+ throw new ConfigException(e.getMessage());
544
+
545
+ // After: chain the cause
546
+ throw new ConfigException("Failed to load config from " + path, e);
547
+ ```
548
+
549
+ ```python
550
+ # Before
551
+ raise ConfigError(str(e))
552
+
553
+ # After: use 'from' to chain
554
+ raise ConfigError(f"Failed to parse {path}") from e
555
+ ```
556
+
557
+ **Detection rule:**
558
+
559
+ Flag `throw new XException(e.getMessage())` -- constructing a new exception from only the message string. Flag Python `raise X` inside an except block without `from`. Lint: `SonarQube S3438`, `Pylint W0707 (raise-missing-from)`.
560
+
561
+ ---
562
+
563
+ ### AP-09: Nested Try-Catch Pyramids
564
+
565
+ **Also known as:** Try-Catch Hell, Tower of Terror, Exception Nesting
566
+ **Frequency:** Common
567
+ **Severity:** Medium
568
+ **Detection difficulty:** Easy
569
+
570
+ **What it looks like:**
571
+
572
+ ```javascript
573
+ try {
574
+ const config = loadConfig();
575
+ try {
576
+ const db = connectDB(config);
577
+ try {
578
+ const data = db.query(sql);
579
+ try {
580
+ return transform(data);
581
+ } catch (transformErr) {
582
+ logger.error("Transform failed", transformErr);
583
+ }
584
+ } catch (queryErr) {
585
+ logger.error("Query failed", queryErr);
586
+ }
587
+ } catch (dbErr) {
588
+ logger.error("DB connection failed", dbErr);
589
+ }
590
+ } catch (configErr) {
591
+ logger.error("Config load failed", configErr);
592
+ }
593
+ ```
594
+
595
+ **Why developers do it:**
596
+
597
+ Each operation needs different error handling, and developers nest them sequentially without extracting functions. Maximiliano Contieri cataloged this as Code Smell #80: "Exceptions are handy. But code is not clear when nesting."
598
+
599
+ **What goes wrong:**
600
+
601
+ Readability collapses. Error handling logic becomes tangled with business logic. The nested structure makes it hard to determine which catch corresponds to which try. Modifying one layer risks breaking the error handling of another.
602
+
603
+ **The fix:**
604
+
605
+ Extract into separate functions with single-level try-catch, or use early returns:
606
+
607
+ ```javascript
608
+ // After: flat structure with extracted functions
609
+ function processRequest() {
610
+ const config = loadConfigSafe(); // throws ConfigError
611
+ const db = connectDBSafe(config); // throws DBError
612
+ const data = querySafe(db, sql); // throws QueryError
613
+ return transformSafe(data); // throws TransformError
614
+ }
615
+
616
+ // Each function handles its own cleanup, throws domain-specific error
617
+ function loadConfigSafe() {
618
+ try {
619
+ return loadConfig();
620
+ } catch (err) {
621
+ throw new ConfigError("Config load failed", { cause: err });
622
+ }
623
+ }
624
+ ```
625
+
626
+ **Detection rule:**
627
+
628
+ Flag try blocks nested more than 2 levels deep. Measure cyclomatic complexity inside catch blocks. Lint: custom rule checking AST nesting depth of try statements.
629
+
630
+ ---
631
+
632
+ ### AP-10: Ignoring Async Errors
633
+
634
+ **Also known as:** Floating Promises, Fire-and-Forget, Unhandled Rejection
635
+ **Frequency:** Very Common
636
+ **Severity:** Critical
637
+ **Detection difficulty:** Hard
638
+
639
+ **What it looks like:**
640
+
641
+ ```javascript
642
+ // No await, no .catch() -- the promise floats
643
+ app.post("/orders", (req, res) => {
644
+ processOrder(req.body); // returns a promise, nobody catches it
645
+ res.json({ status: "accepted" });
646
+ });
647
+
648
+ // Async callback without error handling
649
+ setTimeout(async () => {
650
+ await riskyOperation(); // if this throws, nothing catches it
651
+ }, 1000);
652
+ ```
653
+
654
+ ```python
655
+ # Python: creating a task and forgetting about it
656
+ import asyncio
657
+
658
+ async def handler(request):
659
+ asyncio.create_task(send_notification(request.user)) # fire and forget
660
+ return Response("OK")
661
+ # If send_notification raises, the error is silently dropped
662
+ ```
663
+
664
+ **Why developers do it:**
665
+
666
+ The "fire and forget" pattern seems appropriate for non-critical side effects. Developers forget that async functions return promises that need handling.
667
+
668
+ **What goes wrong:**
669
+
670
+ Starting in Node.js 15, unhandled promise rejections crash the process by default. DZone documented a production incident: "The tiny mistake that crashed our Node.js app" -- a missing `.catch()` on a database cleanup promise. In development it never failed; in production under load, the database connection pool exhausted, the promise rejected, and the entire server process terminated.
671
+
672
+ Before Node 15, unhandled rejections were silently swallowed (a `DeprecationWarning` was the only signal), meaning errors accumulated invisibly.
673
+
674
+ **The fix:**
675
+
676
+ ```javascript
677
+ // Before: floating promise
678
+ processOrder(req.body);
679
+
680
+ // After: await with error handling
681
+ try {
682
+ await processOrder(req.body);
683
+ } catch (err) {
684
+ logger.error("Order processing failed", { orderId: req.body.id, err });
685
+ // decide: retry, dead-letter queue, or error response
686
+ }
687
+
688
+ // For intentional fire-and-forget: explicit void with catch
689
+ void processOrder(req.body).catch(err => {
690
+ logger.error("Background order processing failed", err);
691
+ deadLetterQueue.push({ order: req.body, error: err });
692
+ });
693
+ ```
694
+
695
+ Add global safety nets (but do not rely on them):
696
+
697
+ ```javascript
698
+ process.on('unhandledRejection', (reason, promise) => {
699
+ logger.fatal('Unhandled Rejection', { reason });
700
+ metrics.increment('unhandled.rejection');
701
+ process.exit(1); // fail fast
702
+ });
703
+ ```
704
+
705
+ **Detection rule:**
706
+
707
+ Flag async function calls without `await`, `.then()`, or `.catch()`. TypeScript: enable `@typescript-eslint/no-floating-promises`. ESLint: `require-await`, `no-floating-promises`. Python: flag `asyncio.create_task()` without storing the returned task.
708
+
709
+ ---
710
+
711
+ ### AP-11: Using Assert for Runtime Validation
712
+
713
+ **Also known as:** Assert-as-Guard, Debug-Only Validation
714
+ **Frequency:** Occasional
715
+ **Severity:** Critical
716
+ **Detection difficulty:** Moderate
717
+
718
+ **What it looks like:**
719
+
720
+ ```python
721
+ def transfer_money(from_account, to_account, amount):
722
+ assert amount > 0, "Transfer amount must be positive"
723
+ assert from_account.balance >= amount, "Insufficient funds"
724
+ # proceed with transfer...
725
+ ```
726
+
727
+ ```java
728
+ public void processPayment(double amount) {
729
+ assert amount > 0 : "Amount must be positive";
730
+ // Java assertions disabled by default in production
731
+ }
732
+ ```
733
+
734
+ **Why developers do it:**
735
+
736
+ Assert reads cleanly and communicates intent. It works in tests and development. Developers forget that assertions can be -- and routinely are -- disabled in production.
737
+
738
+ **What goes wrong:**
739
+
740
+ Python's `-O` flag and `PYTHONOPTIMIZE` environment variable strip all assert statements at the bytecode level. Java requires explicit `-ea` to enable assertions, and virtually no production JVM runs with assertions enabled. Snyk's security research documented this as a vulnerability vector: "Disabling asserts in a production environment can be devastating. This practice can introduce various backdoors and breakpoints in the application."
741
+
742
+ A negative transfer amount or insufficient-balance check that only exists as an assert statement becomes a gaping hole in production. Money moves in wrong directions, and the validation that was supposed to prevent it has been compiled away.
743
+
744
+ **The fix:**
745
+
746
+ ```python
747
+ # Before: assert (removed in production with -O)
748
+ assert amount > 0, "Transfer amount must be positive"
749
+
750
+ # After: explicit validation that cannot be disabled
751
+ if amount <= 0:
752
+ raise ValueError(f"Transfer amount must be positive, got {amount}")
753
+
754
+ if from_account.balance < amount:
755
+ raise InsufficientFundsError(
756
+ f"Account {from_account.id} has {from_account.balance}, "
757
+ f"needed {amount}"
758
+ )
759
+ ```
760
+
761
+ Reserve `assert` for:
762
+ - Test assertions (`assert result == expected`)
763
+ - Invariants during development that should never fail (`assert len(sorted_list) == len(original)`)
764
+ - Never for input validation, authorization checks, or business rules
765
+
766
+ **Detection rule:**
767
+
768
+ Flag `assert` statements that reference function parameters, user input, or request data. Lint: `Bandit S101` (Python), `SonarQube S3869` (Java). Snyk rule `python/AssertUsedForSecurity`.
769
+
770
+ ---
771
+
772
+ ### AP-12: Conflating Validation and System Errors
773
+
774
+ **Also known as:** Error Type Confusion, User-Error-as-500, Mixed Error Domains
775
+ **Frequency:** Common
776
+ **Severity:** High
777
+ **Detection difficulty:** Hard
778
+
779
+ **What it looks like:**
780
+
781
+ ```python
782
+ def create_user(data):
783
+ try:
784
+ validate_email(data["email"])
785
+ validate_age(data["age"])
786
+ db.insert(data)
787
+ except Exception as e:
788
+ return {"error": str(e)}, 500 # email typo returns 500 Internal Server Error
789
+ ```
790
+
791
+ ```javascript
792
+ app.post("/users", async (req, res) => {
793
+ try {
794
+ const user = await createUser(req.body);
795
+ res.json(user);
796
+ } catch (err) {
797
+ // ValidationError("invalid email") -> 500
798
+ // DatabaseError("connection refused") -> 500
799
+ // Both return the same status code
800
+ res.status(500).json({ error: "Internal server error" });
801
+ }
802
+ });
803
+ ```
804
+
805
+ **Why developers do it:**
806
+
807
+ A single try-catch is simpler than distinguishing error types. Developers do not create separate exception hierarchies for validation versus system errors.
808
+
809
+ **What goes wrong:**
810
+
811
+ Monitoring systems fire alerts for "invalid email" validation failures as if they were system outages. On-call engineers investigate user typos at 3 AM. Conversely, actual system errors (database down) get the same treatment as bad input, so they may be dismissed as "just more validation noise." SRE teams lose trust in alerts. Users see "Internal Server Error" for fixable input mistakes.
812
+
813
+ **The fix:**
814
+
815
+ ```python
816
+ class ValidationError(AppError):
817
+ """Client-side input error (4xx)."""
818
+ status_code = 400
819
+
820
+ class SystemError(AppError):
821
+ """Server-side infrastructure error (5xx)."""
822
+ status_code = 500
823
+
824
+ def create_user(data):
825
+ # Validation: explicit, returns 4xx
826
+ errors = validate_user_input(data)
827
+ if errors:
828
+ raise ValidationError(errors)
829
+
830
+ # System operation: may throw 5xx
831
+ try:
832
+ return db.insert(data)
833
+ except DatabaseError as e:
834
+ raise SystemError("Failed to create user") from e
835
+ ```
836
+
837
+ **Detection rule:**
838
+
839
+ Flag catch blocks that return HTTP 500 for all exception types without distinguishing. Flag error hierarchies where validation and system exceptions share a common non-root base class.
840
+
841
+ ---
842
+
843
+ ### AP-13: Stringly-Typed Errors
844
+
845
+ **Also known as:** Error String Matching, Message-Based Dispatch, Error-Message-as-API
846
+ **Frequency:** Common
847
+ **Severity:** High
848
+ **Detection difficulty:** Moderate
849
+
850
+ **What it looks like:**
851
+
852
+ ```go
853
+ if err != nil {
854
+ if strings.Contains(err.Error(), "connection refused") {
855
+ retryConnection()
856
+ } else if strings.Contains(err.Error(), "timeout") {
857
+ extendTimeout()
858
+ }
859
+ }
860
+ ```
861
+
862
+ ```javascript
863
+ try {
864
+ await api.call();
865
+ } catch (err) {
866
+ if (err.message.includes("rate limit")) {
867
+ await sleep(1000);
868
+ return api.call();
869
+ }
870
+ }
871
+ ```
872
+
873
+ **Why developers do it:**
874
+
875
+ The error type system is not expressive enough, or the library only returns generic errors with different messages. Quick pattern matching on strings is faster to write than proper type checking.
876
+
877
+ **What goes wrong:**
878
+
879
+ Dave Cheney, in his widely-cited Go blog post, stated: "Comparing the string form of an error is, in my opinion, a code smell. You should try to avoid it." The error message is for humans, not code. When a library author rephrases "connection refused" to "unable to connect," every string-matching caller silently breaks. There is no compiler or type checker to catch the regression. These bugs only manifest at runtime, under the exact failure condition being matched.
880
+
881
+ **The fix:**
882
+
883
+ ```go
884
+ // Before: string matching
885
+ if strings.Contains(err.Error(), "connection refused") {
886
+ retryConnection()
887
+ }
888
+
889
+ // After: use error types and errors.Is / errors.As
890
+ var connErr *net.OpError
891
+ if errors.As(err, &connErr) {
892
+ retryConnection()
893
+ }
894
+ ```
895
+
896
+ ```javascript
897
+ // Before: string matching
898
+ if (err.message.includes("rate limit")) { ... }
899
+
900
+ // After: use error codes or typed errors
901
+ if (err instanceof RateLimitError) { ... }
902
+ // or
903
+ if (err.code === "RATE_LIMITED") { ... }
904
+ ```
905
+
906
+ **Detection rule:**
907
+
908
+ Flag `err.Error()`, `err.message`, or `e.getMessage()` used inside string comparison functions (`contains`, `includes`, `equals`, `startsWith`). Lint: `errorlint` (Go), custom ESLint rule for `err.message.includes`.
909
+
910
+ ---
911
+
912
+ ### AP-14: Missing Error Boundaries
913
+
914
+ **Also known as:** White Screen of Death, Unbounded Error Propagation, No Blast Radius
915
+ **Frequency:** Common
916
+ **Severity:** High
917
+ **Detection difficulty:** Moderate
918
+
919
+ **What it looks like:**
920
+
921
+ ```jsx
922
+ // React app with no error boundary
923
+ function App() {
924
+ return (
925
+ <Dashboard>
926
+ <UserProfile /> {/* if this throws, entire app dies */}
927
+ <OrderHistory />
928
+ <Notifications />
929
+ </Dashboard>
930
+ );
931
+ }
932
+ ```
933
+
934
+ **Why developers do it:**
935
+
936
+ Error boundaries require class components in React (no hook equivalent for `componentDidCatch`). Developers building with functional components skip them because they feel archaic. In backend systems, developers rely on global exception handlers without module-level boundaries.
937
+
938
+ **What goes wrong:**
939
+
940
+ React's own documentation states: "As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree." A single `TypeError` in a `UserProfile` widget takes down the entire application, rendering a blank white page. Wix Engineering documented this as the "White Screen of Death" for React Native, where uncaught errors crashed the entire app instead of just the offending component.
941
+
942
+ FreeCodeCamp documented the pattern: "Everything is set up and works properly, but the application crashes in production because of a missed little error, and then the whole screen goes white while clicking some button."
943
+
944
+ **The fix:**
945
+
946
+ ```jsx
947
+ // Wrap independent features in separate error boundaries
948
+ function App() {
949
+ return (
950
+ <Dashboard>
951
+ <ErrorBoundary fallback={<ProfileError />}>
952
+ <UserProfile />
953
+ </ErrorBoundary>
954
+ <ErrorBoundary fallback={<OrdersUnavailable />}>
955
+ <OrderHistory />
956
+ </ErrorBoundary>
957
+ <ErrorBoundary fallback={<NotificationsOff />}>
958
+ <Notifications />
959
+ </ErrorBoundary>
960
+ </Dashboard>
961
+ );
962
+ }
963
+ ```
964
+
965
+ In backend systems, use bulkheads:
966
+
967
+ ```python
968
+ # Process each item independently; one failure doesn't stop the batch
969
+ results = []
970
+ for item in batch:
971
+ try:
972
+ results.append(process(item))
973
+ except ProcessingError as e:
974
+ logger.error("Item %s failed: %s", item.id, e)
975
+ results.append(FailedResult(item.id, e))
976
+ ```
977
+
978
+ **Detection rule:**
979
+
980
+ In React: flag component trees with more than 50 components and no `ErrorBoundary` wrapper. In backends: flag batch-processing loops without per-item error handling. Lint: `eslint-plugin-react` custom rule for error boundary coverage.
981
+
982
+ ---
983
+
984
+ ### AP-15: Not Using Finally / Cleanup
985
+
986
+ **Also known as:** Resource Leak Pattern, Missing Cleanup, Dangling Handles
987
+ **Frequency:** Common
988
+ **Severity:** High
989
+ **Detection difficulty:** Hard
990
+
991
+ **What it looks like:**
992
+
993
+ ```java
994
+ Connection conn = null;
995
+ try {
996
+ conn = dataSource.getConnection();
997
+ PreparedStatement stmt = conn.prepareStatement(sql);
998
+ ResultSet rs = stmt.executeQuery();
999
+ return processResults(rs);
1000
+ } catch (SQLException e) {
1001
+ throw new DataAccessException(e);
1002
+ }
1003
+ // conn, stmt, rs never closed if exception occurs in processResults
1004
+ ```
1005
+
1006
+ ```python
1007
+ f = open("/tmp/data.csv", "w")
1008
+ f.write(generate_report()) # if this throws, file handle leaks
1009
+ f.close()
1010
+ ```
1011
+
1012
+ **Why developers do it:**
1013
+
1014
+ They assume the happy path always completes. In garbage-collected languages, they assume the GC will clean up (it does not close file handles, database connections, or network sockets).
1015
+
1016
+ **What goes wrong:**
1017
+
1018
+ Connection pool exhaustion is the classic symptom. Under normal load, connections are returned. Under error conditions, leaked connections accumulate until the pool is exhausted and the entire application blocks waiting for connections. This failure mode only manifests under stress -- exactly when you can least afford it.
1019
+
1020
+ **The fix:**
1021
+
1022
+ ```java
1023
+ // Before: manual cleanup (leak-prone)
1024
+ Connection conn = dataSource.getConnection();
1025
+ // ...
1026
+
1027
+ // After: try-with-resources (Java 7+)
1028
+ try (Connection conn = dataSource.getConnection();
1029
+ PreparedStatement stmt = conn.prepareStatement(sql);
1030
+ ResultSet rs = stmt.executeQuery()) {
1031
+ return processResults(rs);
1032
+ }
1033
+ ```
1034
+
1035
+ ```python
1036
+ # Before
1037
+ f = open("/tmp/data.csv", "w")
1038
+ f.write(generate_report())
1039
+ f.close()
1040
+
1041
+ # After: context manager
1042
+ with open("/tmp/data.csv", "w") as f:
1043
+ f.write(generate_report())
1044
+ ```
1045
+
1046
+ ```javascript
1047
+ // JavaScript: use finally for cleanup
1048
+ const client = await pool.connect();
1049
+ try {
1050
+ return await client.query(sql);
1051
+ } finally {
1052
+ client.release();
1053
+ }
1054
+
1055
+ // Or with Symbol.asyncDispose (TC39 Stage 3)
1056
+ await using client = await pool.connect();
1057
+ return await client.query(sql);
1058
+ ```
1059
+
1060
+ **Detection rule:**
1061
+
1062
+ Flag `Connection`, `InputStream`, `FileHandle` allocations not inside try-with-resources or `with` blocks. Lint: `SonarQube S2095`, `SpotBugs OBL_UNSATISFIED_OBLIGATION`, `Pylint R1732 (consider-using-with)`.
1063
+
1064
+ ---
1065
+
1066
+ ### AP-16: Error Codes vs Exceptions Confusion
1067
+
1068
+ **Also known as:** Mixed Signaling, Dual Error System, Return-Code-in-Exception-Land
1069
+ **Frequency:** Occasional
1070
+ **Severity:** Medium
1071
+ **Detection difficulty:** Hard
1072
+
1073
+ **What it looks like:**
1074
+
1075
+ ```python
1076
+ # Mixing paradigms: returns error codes AND throws exceptions
1077
+ def process_payment(order):
1078
+ result = gateway.charge(order.amount)
1079
+ if result.status_code == -1:
1080
+ return {"error": "payment_declined", "code": -1}
1081
+ if result.status_code == -2:
1082
+ raise PaymentGatewayError("Gateway unreachable")
1083
+ if result.status_code == 0:
1084
+ return {"success": True}
1085
+ # What about status_code == -3? Undefined behavior.
1086
+ ```
1087
+
1088
+ ```go
1089
+ // Go: returning both error and value, caller ignores error
1090
+ result, err := processPayment(order)
1091
+ // Developer checks result but not err
1092
+ if result.Success {
1093
+ completeOrder(order)
1094
+ }
1095
+ ```
1096
+
1097
+ **Why developers do it:**
1098
+
1099
+ Different team members prefer different styles. Legacy code uses error codes, new code uses exceptions, and they meet at integration points. Go's `(value, error)` convention can be undermined when callers check only the value.
1100
+
1101
+ **What goes wrong:**
1102
+
1103
+ Callers do not know which error channel to check. Some callers check the return value, others wrap in try-catch, and some do both. The LWN.net article on "Exceptions vs Error Codes" documents how mixing paradigms leads to unhandled error paths because callers make incorrect assumptions about which mechanism signals failure.
1104
+
1105
+ **The fix:**
1106
+
1107
+ Pick one paradigm per language/module boundary and enforce it:
1108
+
1109
+ ```python
1110
+ # Before: mixed
1111
+ def process_payment(order):
1112
+ result = gateway.charge(order.amount)
1113
+ if result.status_code == -1:
1114
+ return {"error": "payment_declined"}
1115
+ if result.status_code == -2:
1116
+ raise PaymentGatewayError("unreachable")
1117
+
1118
+ # After: exceptions only (Python/Java/JS convention)
1119
+ def process_payment(order):
1120
+ """Raises PaymentDeclined or GatewayUnreachable. Returns OrderReceipt on success."""
1121
+ result = gateway.charge(order.amount)
1122
+ if result.status_code == -1:
1123
+ raise PaymentDeclined(order_id=order.id, reason=result.message)
1124
+ if result.status_code == -2:
1125
+ raise GatewayUnreachable(gateway=gateway.name)
1126
+ return OrderReceipt(result)
1127
+ ```
1128
+
1129
+ **Detection rule:**
1130
+
1131
+ Flag functions that both `return error_dict` and `raise Exception` in different branches. Flag Go functions where the caller uses the first return value without checking `err != nil`. Lint: `errcheck` (Go), custom AST rule for mixed return/raise.
1132
+
1133
+ ---
1134
+
1135
+ ### AP-17: Panic-Driven Error Handling
1136
+
1137
+ **Also known as:** Crash-Happy Code, Fail-Loud Everywhere, Panic-as-Error
1138
+ **Frequency:** Occasional
1139
+ **Severity:** High
1140
+ **Detection difficulty:** Easy
1141
+
1142
+ **What it looks like:**
1143
+
1144
+ ```go
1145
+ func loadConfig(path string) Config {
1146
+ data, err := os.ReadFile(path)
1147
+ if err != nil {
1148
+ panic("failed to read config: " + err.Error())
1149
+ }
1150
+ var cfg Config
1151
+ if err := json.Unmarshal(data, &cfg); err != nil {
1152
+ panic("failed to parse config: " + err.Error())
1153
+ }
1154
+ return cfg
1155
+ }
1156
+ ```
1157
+
1158
+ ```rust
1159
+ fn get_user(id: &str) -> User {
1160
+ db.find_user(id).unwrap() // panics on None
1161
+ }
1162
+ ```
1163
+
1164
+ **Why developers do it:**
1165
+
1166
+ "If this fails, nothing else matters" reasoning. In Go, the `panic`/`recover` mechanism looks like exceptions, tempting developers to use it as one. In Rust, `.unwrap()` is shorter than proper error propagation.
1167
+
1168
+ **What goes wrong:**
1169
+
1170
+ Go's official documentation states: "Don't use panic for normal error handling. Use error and multiple return values." Eli Bendersky documented how panic breaks the natural control flow of the program, surprising other developers. In Go's `net/http`, panics in request handlers are recovered by the server, but David Symonds (from the Go team) noted this may itself be an anti-pattern: "Quietly catching a panic might leave the server in an inconsistent or incorrect state."
1171
+
1172
+ A config file missing on one server in a fleet should not crash the process -- it should use a fallback or degrade gracefully. A database lookup returning no result is not a panic-worthy event.
1173
+
1174
+ **The fix:**
1175
+
1176
+ ```go
1177
+ // Before: panic
1178
+ func loadConfig(path string) Config {
1179
+ data, err := os.ReadFile(path)
1180
+ if err != nil {
1181
+ panic("failed to read config")
1182
+ }
1183
+ // ...
1184
+ }
1185
+
1186
+ // After: return error
1187
+ func loadConfig(path string) (Config, error) {
1188
+ data, err := os.ReadFile(path)
1189
+ if err != nil {
1190
+ return Config{}, fmt.Errorf("reading config %s: %w", path, err)
1191
+ }
1192
+ var cfg Config
1193
+ if err := json.Unmarshal(data, &cfg); err != nil {
1194
+ return Config{}, fmt.Errorf("parsing config %s: %w", path, err)
1195
+ }
1196
+ return cfg, nil
1197
+ }
1198
+ ```
1199
+
1200
+ ```rust
1201
+ // Before
1202
+ fn get_user(id: &str) -> User {
1203
+ db.find_user(id).unwrap()
1204
+ }
1205
+
1206
+ // After
1207
+ fn get_user(id: &str) -> Result<User, DbError> {
1208
+ db.find_user(id).ok_or_else(|| DbError::NotFound(id.to_string()))
1209
+ }
1210
+ ```
1211
+
1212
+ **Detection rule:**
1213
+
1214
+ Flag `panic()` calls in Go outside of `init()` or test files. Flag `.unwrap()` in Rust outside of tests. Lint: `clippy::unwrap_used`, `golangci-lint gocritic panic` rule.
1215
+
1216
+ ---
1217
+
1218
+ ### AP-18: Destructive Finally Blocks
1219
+
1220
+ **Also known as:** Finally Swallows Exception, Return-in-Finally, Finally Override
1221
+ **Frequency:** Rare but Catastrophic
1222
+ **Severity:** Critical
1223
+ **Detection difficulty:** Very Hard
1224
+
1225
+ **What it looks like:**
1226
+
1227
+ ```java
1228
+ public int calculate() {
1229
+ try {
1230
+ throw new RuntimeException("Critical error");
1231
+ } finally {
1232
+ return 42; // silently swallows the RuntimeException
1233
+ }
1234
+ }
1235
+ // Returns 42. No exception propagated. No trace. Nothing.
1236
+ ```
1237
+
1238
+ ```python
1239
+ def calculate():
1240
+ try:
1241
+ raise ValueError("Critical error")
1242
+ finally:
1243
+ return 42 # ValueError silently discarded
1244
+ ```
1245
+
1246
+ **Why developers do it:**
1247
+
1248
+ They add a `return` in `finally` as a "safety net" to ensure the method always returns something. They do not realize that a return in `finally` overrides any exception being propagated.
1249
+
1250
+ **What goes wrong:**
1251
+
1252
+ The exception is silently discarded -- not caught, not logged, not propagated. It simply ceases to exist. Vishal Junghare documented this in Java: "A finally block can quietly swallow exceptions." This is one of the most insidious bugs because it leaves zero evidence. The method returns a plausible-looking value (42), making the bug extremely hard to detect.
1253
+
1254
+ **The fix:**
1255
+
1256
+ Never return from a finally block. Use finally only for cleanup:
1257
+
1258
+ ```java
1259
+ // Before: return in finally swallows exception
1260
+ public int calculate() {
1261
+ try {
1262
+ return riskyComputation();
1263
+ } finally {
1264
+ return 42;
1265
+ }
1266
+ }
1267
+
1268
+ // After: finally only for cleanup
1269
+ public int calculate() {
1270
+ try {
1271
+ return riskyComputation();
1272
+ } finally {
1273
+ cleanupResources(); // no return statement
1274
+ }
1275
+ }
1276
+ ```
1277
+
1278
+ **Detection rule:**
1279
+
1280
+ Flag `return` statements inside `finally` blocks. Lint: `SonarQube S1143`, `PMD ReturnFromFinallyBlock`, `Pylint W0150 (lost-exception)`, `ESLint no-unsafe-finally`.
1281
+
1282
+ ---
1283
+
1284
+ ## Root Cause Analysis
1285
+
1286
+ | Root Cause | Anti-Patterns | Frequency |
1287
+ |---|---|---|
1288
+ | **Lack of testing error paths** | AP-01, AP-02, AP-06, AP-10, AP-18 | Very High |
1289
+ | **Time pressure / "ship it" culture** | AP-01, AP-02, AP-07, AP-09 | Very High |
1290
+ | **Not understanding language semantics** | AP-06, AP-11, AP-17, AP-18 | High |
1291
+ | **Cargo-cult defensive programming** | AP-01, AP-06, AP-04 | High |
1292
+ | **Missing error type hierarchy** | AP-07, AP-12, AP-13, AP-16 | High |
1293
+ | **Over-applying security guidance** | AP-07, AP-08 | Medium |
1294
+ | **Unfamiliarity with async model** | AP-10, AP-15 | High |
1295
+ | **No code review standards for error handling** | AP-02, AP-05, AP-09 | High |
1296
+ | **Copy-paste from Stack Overflow** | AP-03, AP-09, AP-17 | Medium |
1297
+ | **GC creating false sense of safety** | AP-15, AP-04 | Medium |
1298
+
1299
+ ---
1300
+
1301
+ ## Self-Check Questions
1302
+
1303
+ Use these during code review or self-review. A "yes" answer indicates a potential anti-pattern.
1304
+
1305
+ 1. **Does any catch block have an empty body, or only a comment/TODO?** (AP-02)
1306
+ 2. **Does any catch clause use the broadest possible exception type (`Exception`, `Throwable`, `BaseException`, bare `catch`)?** (AP-01, AP-06)
1307
+ 3. **Are there catch blocks that both log the exception AND rethrow it?** (AP-05)
1308
+ 4. **Does any function catch an exception and return null without documenting why?** (AP-04)
1309
+ 5. **Are there `assert` statements validating user input, authorization, or business rules?** (AP-11)
1310
+ 6. **Do any catch blocks construct a new exception using only `e.getMessage()` without chaining the cause?** (AP-08)
1311
+ 7. **Is error string content (`e.message`, `err.Error()`) compared using `contains`, `includes`, or `equals`?** (AP-13)
1312
+ 8. **Are there async function calls without `await`, `.catch()`, or stored task references?** (AP-10)
1313
+ 9. **Do HTTP handlers return the same status code (usually 500) for validation errors and system errors?** (AP-12)
1314
+ 10. **Are there `return` statements inside `finally` blocks?** (AP-18)
1315
+ 11. **Do resource allocations (connections, file handles, locks) occur outside try-with-resources or context managers?** (AP-15)
1316
+ 12. **Are try-catch blocks nested more than 2 levels deep?** (AP-09)
1317
+ 13. **Does the codebase mix error-code returns and exceptions for the same type of failure?** (AP-16)
1318
+ 14. **Are there `panic()` or `.unwrap()` calls in non-initialization, non-test code?** (AP-17)
1319
+ 15. **Does the React component tree have more than 50 components without any `ErrorBoundary`?** (AP-14)
1320
+
1321
+ ---
1322
+
1323
+ ## Code Smell Quick Reference
1324
+
1325
+ | Smell | Pattern to Look For | Likely Anti-Pattern | Severity |
1326
+ |---|---|---|---|
1327
+ | `except Exception: pass` | Bare catch with empty body | AP-01 + AP-02 | Critical |
1328
+ | `catch (Throwable t)` | Catching JVM-level errors | AP-06 | Critical |
1329
+ | `return null` in catch block | Exception converted to null | AP-04 | High |
1330
+ | `logger.error(e); throw e;` | Log followed by rethrow | AP-05 | Medium |
1331
+ | `throw new X(e.getMessage())` | New exception from message only | AP-08 | Medium |
1332
+ | `assert user_input > 0` | Assert on external input | AP-11 | Critical |
1333
+ | `int.Parse` in try-catch | Exception as flow control | AP-03 | Medium |
1334
+ | `err.message.includes("...")` | String-matching on error text | AP-13 | High |
1335
+ | `processAsync(x)` (no await) | Floating promise | AP-10 | Critical |
1336
+ | Nested `try { try { try {` | 3+ nesting levels | AP-09 | Medium |
1337
+ | `return 42` inside `finally` | Return overriding exception | AP-18 | Critical |
1338
+ | `res.status(500)` for all errors | No error type distinction | AP-12 | High |
1339
+ | `panic("not found")` | Panic for expected condition | AP-17 | High |
1340
+ | No `ErrorBoundary` in React tree | Uncontained error blast radius | AP-14 | High |
1341
+ | `conn = getConnection()` without `try-finally` | Resource outside cleanup block | AP-15 | High |
1342
+ | Function returns error dict AND raises | Mixed error signaling | AP-16 | Medium |
1343
+
1344
+ ---
1345
+
1346
+ ## Key Research
1347
+
1348
+ The University of Toronto study "Simple Testing Can Prevent Most Critical Failures" (OSDI 2014, Yuan et al.) analyzed 198 failures across Cassandra, HBase, HDFS, MapReduce, and Redis. Core findings relevant to this module:
1349
+
1350
+ - **92%** of catastrophic failures resulted from incorrect handling of non-fatal errors
1351
+ - **35%** had trivial error-handling bugs (empty handlers, log-only handlers, incomplete logic)
1352
+ - **77%** of failures could be reproduced by a unit test
1353
+ - **98%** manifested on no more than 3 nodes
1354
+ - The authors built Aspirator, a static checker that automatically detected these bugs
1355
+
1356
+ This research provides empirical backing for why error handling anti-patterns are not theoretical concerns -- they are the primary cause of production catastrophes in distributed systems.
1357
+
1358
+ ---
1359
+
1360
+ *Researched: 2026-03-08 | Sources: Yuan et al. "Simple Testing Can Prevent Most Critical Failures" (OSDI 2014), Harness.io "Swallowed Exceptions: The Silent Killer of Java Applications", DZone "The Tiny Mistake That Crashed Our Node.js App", Tony Hoare "Null References: The Billion-Dollar Mistake" (QCon 2009), Dave Cheney "Don't just check errors, handle them gracefully", TheServerSide "Either log or rethrow Java exceptions", Baeldung "Is It a Bad Practice to Catch Throwable?", React documentation on Error Boundaries, Wix Engineering "White Screen of Death", Snyk "The dangers of assert in Python", Eli Bendersky "On the uses and misuses of panics in Go", SonarQube rules S2139/S1181/S108/S2095, CWE-397, OWASP Top 10 Proactive Controls C10, Maximiliano Contieri "Code Smell 80 - Nested Try/Catch", n8n Issue #19434, Databricks SDK Issue #1117*