async-error-handling

Guides correct error handling and Promise composition in JavaScript and TypeScript async code.

1|Updated Apr 3, 2026
One-click install
npx skills add https://github.com/TierOne-Studio/spa-velocity --skill async-error-handling-tierone-studio
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: async-error-handling
Source: https://github.com/TierOne-Studio/spa-velocity/tree/main/.ruler/skills/async-error-handling
Command: npx skills add https://github.com/TierOne-Studio/spa-velocity --skill async-error-handling-tierone-studio

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Async JavaScript and TypeScript code is where LLM-generated code most often goes wrong: defensive try/catch on every function, returning null instead of throwing, misusing Promise.all when partial failure is acceptable, and building timeouts with Promise.race that leak resources. This Skill encodes the correct fail-fast patterns so async code propagates errors to the right boundary instead of silently swallowing them. ## Core Features & Use Cases - Error propagation rules: Throw typed errors instead of returning null, catch only at boundaries (user-action handlers, transformations, fan-in aggregators), and never catch-and-ignore. - Promise composition decision tree: Choose between Promise.all, allSettled, race, and any, and avoid common traps like await inside .map() or async .forEach(). - Timeouts and cancellation: Use AbortSignal.timeout() and propagate TanStack Query's signal so cancellation actually cancels the underlying fetch. - Use Case: When writing a multi-source chat search where one source timing out must not blank the whole response, apply the Promise.allSettled pattern with per-source failure logging. ## Quick Start Review my async data-fetching code and fix any incorrect try/catch placement, Promise composition, or missing AbortSignal propagation.

Frequently Asked Questions about async-error-handling

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I handle errors in async JavaScript and TypeScript code?

Throw typed errors instead of returning null, and let them propagate to a boundary such as a TanStack Query hook, error boundary, or click handler. Catch only when transforming an error, recovering with a proven fallback, or handling a user action directly.

When should I use Promise.all vs Promise.allSettled?

Use Promise.all when every operation must succeed and one failure should abort the whole result. Use Promise.allSettled when partial success is acceptable, such as querying multiple independent data sources where one timeout should not blank the response.

How do I add a timeout to a fetch request in JavaScript?

Use AbortSignal.timeout(milliseconds) and pass the signal to fetch, which actually cancels the underlying operation. Avoid Promise.race with a setTimeout rejection, since the original operation keeps running and leaks resources.

Why is await inside .map() not sequential?

An async callback in .map() starts all iterations immediately, so operations run in parallel rather than waiting for each other. For sequential execution use a for-of loop with await; for explicit parallelism use Promise.all with map.

Does TanStack Query handle retries and cancellation automatically?

TanStack Query has its own retry configuration, so set it intentionally (for example retry: false on mutations) instead of wrapping fetches in custom retry loops. It also passes an AbortSignal to queryFn, which you should forward to the underlying fetch so cancellation cascades.

When should I not apply async error handling patterns?

Skip these patterns for synchronous control flow, a single await followed by return with no error-flow decision, and React useEffect cleanup where the framework already swallows errors. Adding try/catch in those cases only adds noise and hides root causes.