error-handling-fundamentals
try/catch処理、APIエラー対応、非同期処理、ユーザーフィードバックなど、エラーが発生しやすい箇所をチェックし、システムがスムーズに動き続け、分かりやすいエラーメッセージを表示するように改善するSkill。
📜 元の英語説明(参考)
Auto-invoke when reviewing try/catch blocks, API error responses, async operations, or user feedback patterns. Enforces graceful degradation and meaningful error messages.
🇯🇵 日本人クリエイター向け解説
try/catch処理、APIエラー対応、非同期処理、ユーザーフィードバックなど、エラーが発生しやすい箇所をチェックし、システムがスムーズに動き続け、分かりやすいエラーメッセージを表示するように改善するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o error-handling-fundamentals.zip https://jpskill.com/download/18281.zip && unzip -o error-handling-fundamentals.zip && rm error-handling-fundamentals.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/18281.zip -OutFile "$d\error-handling-fundamentals.zip"; Expand-Archive "$d\error-handling-fundamentals.zip" -DestinationPath $d -Force; ri "$d\error-handling-fundamentals.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
error-handling-fundamentals.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
error-handling-fundamentalsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
エラー処理の基礎レビュー
「エラーは失敗ではありません。情報です。価値のあるデータとして扱いましょう。」
適用するタイミング
以下のレビュー時にこのスキルを適用します。
- try/catch ブロック
- Promise チェーン (.then/.catch)
- API エラーレスポンス
- フォームのバリデーション
- ネットワークリクエストの処理
- ユーザー向けのエラーメッセージ
レビューチェックリスト
エラーキャッチ
- [ ] 空の catch がないか: すべての catch ブロックが意味のある処理をしていますか?
- [ ] 適切なスコープ: エラーは適切なレベルでキャッチされていますか?
- [ ] コンテキストの追加: エラーには役立つデバッグ情報が含まれていますか?
- [ ] finally の使用: クリーンアップ処理は finally ブロックに記述されていますか?
ユーザーエクスペリエンス
- [ ] ユーザーフレンドリーなメッセージ: ユーザーはそのエラーを理解できますか?
- [ ] 技術的な詳細の非表示: スタックトレースはユーザーに公開されていませんか?
- [ ] 実行可能なフィードバック: エラーはユーザーに次に何をすべきかを伝えていますか?
- [ ] グレースフルデグラデーション: エラーが発生してもアプリは部分的に動作しますか?
ロギングとデバッグ
- [ ] エラーのログ: エラーはデバッグのために記録されていますか?
- [ ] ログのコンテキスト: ログにはリクエスト ID、ユーザー ID などが含まれていますか?
- [ ] 重要度レベル: 重大なエラーは警告と区別されていますか?
リカバリー
- [ ] リトライロジック: この操作は失敗時にリトライすべきですか?
- [ ] フォールバック値: エラー時に適切なデフォルト値はありますか?
- [ ] ローディング状態: リトライ中にユーザーに通知されますか?
よくある間違い (アンチパターン)
1. 空の Catch (静かなる殺人者)
❌ try {
await submitForm();
} catch (error) {
// TODO: 後で処理する (決して起こらない)
}
✅ try {
await submitForm();
} catch (error) {
console.error('Form submission failed:', error);
setError('Could not submit. Please try again.');
}
2. 早すぎる Catch
❌ function getUser(id) {
try {
return database.query(id);
} catch {
return null; // 呼び出し元は失敗したことに気づかない
}
}
✅ function getUser(id) {
return database.query(id); // 呼び出し元に判断させる
}
// UI レイヤーで
try {
const user = await getUser(id);
} catch (error) {
showToast('Could not load user');
}
3. 汎用的なエラーメッセージ
❌ catch (error) {
setError('An error occurred');
}
✅ catch (error) {
if (error.code === 'NETWORK_ERROR') {
setError('Check your internet connection');
} else if (error.code === 'NOT_FOUND') {
setError('User not found');
} else {
setError('Something went wrong. Please try again.');
}
}
4. スタックトレースのリーク
❌ res.status(500).json({
error: error.message,
stack: error.stack
});
✅ logger.error('Request failed', { error, requestId });
res.status(500).json({
error: 'Something went wrong'
});
5. finally の忘れ
❌ try {
setLoading(true);
await fetchData();
setLoading(false);
} catch (error) {
handleError(error);
// Loading が永遠に true のまま!
}
✅ try {
setLoading(true);
await fetchData();
} catch (error) {
handleError(error);
} finally {
setLoading(false); // 常に実行される
}
ソクラテス式質問
ジュニアに答えを与える代わりに、これらの質問をしてください。
- 空の Catch: 「これが何も言わずに失敗したらどうなりますか?」
- ユーザーメッセージ: 「あなたがユーザーなら、このメッセージは役に立ちますか?」
- リカバリー: 「これを自動的にリトライすべきですか?」
- スコープ: 「これはこのエラーをキャッチするのに適切な場所ですか?」
- ロギング: 「本番環境でこれをどのようにデバッグしますか?」
エラーメッセージのガイドライン
すること
- 具体的にする: 「そのメールアドレスはすでに登録されています」
- 役に立つようにする: 「インターネット接続を確認してください」
- 次のステップを提供する: 「もう一度試してください」または「サポートに連絡してください」
- 重要度を一致させる: 重大なエラーは警告よりも注意が必要です
しないこと
- 技術的な詳細を表示する:
TypeError: Cannot read property 'map' of undefined - 曖昧にする: 「エラーが発生しました」
- ユーザーを責める: 「無効なデータを入力しました」
- 専門用語を使う: 「HTTP 500 Internal Server Error」
エラー処理パターン
API/ネットワークエラー
async function fetchWithRetry(url: string, retries = 3): Promise<Response> {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response;
} catch (error) {
if (retries > 0) {
await sleep(1000);
return fetchWithRetry(url, retries - 1);
}
throw error;
}
}
フォームのバリデーション
function validateForm(data: FormData) {
const errors: Record<string, string> = {};
if (!data.email) {
errors.email = 'Email is required';
} else if (!isValidEmail(data.email)) {
errors.email = 'Please enter a valid email';
}
return {
isValid: Object.keys(errors).length === 0,
errors
};
}
React エラー境界
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
logError(error, info);
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
標準リファレンス
詳細なパターンについては以下を参照してください。
/standards/global/error-handling.md
指摘すべき危険信号
| フラグ | 質問 |
|---|---|
| 空の catch ブロック | 「これが失敗したらどうなりますか?」 |
catch (e) { return null } |
「呼び出し元はどうやって失敗したことを知るのですか?」 |
| ローディング状態がない | 「ユーザーは待っている間何を見ますか?」 |
| 技術的なエラーが表示される | 「ユーザーはこのメッセージを理解できますか?」 |
| クリーンアップのための finally がない | 「ローディング状態はエラー時にスタックしますか?」 |
| console.log の代わりに error | 「本番環境のログでこれをどのように見つけますか?」 |
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Error Handling Fundamentals Review
"Errors are not failures — they're information. Handle them like the valuable data they are."
When to Apply
Activate this skill when reviewing:
- try/catch blocks
- Promise chains (.then/.catch)
- API error responses
- Form validation
- Network request handling
- User-facing error messages
Review Checklist
Error Catching
- [ ] No empty catches: Is every catch block doing something meaningful?
- [ ] Proper scope: Are errors caught at the right level?
- [ ] Context added: Do errors include helpful debugging info?
- [ ] Finally used: Are cleanup operations in finally blocks?
User Experience
- [ ] User-friendly messages: Will users understand the error?
- [ ] No technical details exposed: Are stack traces hidden from users?
- [ ] Actionable feedback: Does the error tell users what to do next?
- [ ] Graceful degradation: Does the app still work partially on error?
Logging & Debugging
- [ ] Errors logged: Are errors recorded for debugging?
- [ ] Context in logs: Do logs include request ID, user ID, etc.?
- [ ] Severity levels: Are critical errors distinguished from warnings?
Recovery
- [ ] Retry logic: Should this operation retry on failure?
- [ ] Fallback values: Is there a sensible default on error?
- [ ] Loading states: Is the user informed while retrying?
Common Mistakes (Anti-Patterns)
1. The Empty Catch (The Silent Killer)
❌ try {
await submitForm();
} catch (error) {
// TODO: handle later (never happens)
}
✅ try {
await submitForm();
} catch (error) {
console.error('Form submission failed:', error);
setError('Could not submit. Please try again.');
}
2. Catching Too Early
❌ function getUser(id) {
try {
return database.query(id);
} catch {
return null; // Caller has no idea it failed
}
}
✅ function getUser(id) {
return database.query(id); // Let caller decide
}
// In UI layer
try {
const user = await getUser(id);
} catch (error) {
showToast('Could not load user');
}
3. Generic Error Messages
❌ catch (error) {
setError('An error occurred');
}
✅ catch (error) {
if (error.code === 'NETWORK_ERROR') {
setError('Check your internet connection');
} else if (error.code === 'NOT_FOUND') {
setError('User not found');
} else {
setError('Something went wrong. Please try again.');
}
}
4. Leaking Stack Traces
❌ res.status(500).json({
error: error.message,
stack: error.stack
});
✅ logger.error('Request failed', { error, requestId });
res.status(500).json({
error: 'Something went wrong'
});
5. Forgetting Finally
❌ try {
setLoading(true);
await fetchData();
setLoading(false);
} catch (error) {
handleError(error);
// Loading stays true forever!
}
✅ try {
setLoading(true);
await fetchData();
} catch (error) {
handleError(error);
} finally {
setLoading(false); // Always runs
}
Socratic Questions
Ask the junior these questions instead of giving answers:
- Empty Catch: "What happens if this fails silently?"
- User Message: "If you were the user, would this message help you?"
- Recovery: "Should we retry this automatically?"
- Scope: "Is this the right place to catch this error?"
- Logging: "How will you debug this in production?"
Error Message Guidelines
Do
- Be specific: "The email address is already registered"
- Be helpful: "Please check your internet connection"
- Offer next steps: "Try again" or "Contact support"
- Match severity: Critical errors need more attention than warnings
Don't
- Show technical details:
TypeError: Cannot read property 'map' of undefined - Be vague: "An error occurred"
- Blame the user: "You entered invalid data"
- Use jargon: "HTTP 500 Internal Server Error"
Error Handling Patterns
API/Network Errors
async function fetchWithRetry(url: string, retries = 3): Promise<Response> {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response;
} catch (error) {
if (retries > 0) {
await sleep(1000);
return fetchWithRetry(url, retries - 1);
}
throw error;
}
}
Form Validation
function validateForm(data: FormData) {
const errors: Record<string, string> = {};
if (!data.email) {
errors.email = 'Email is required';
} else if (!isValidEmail(data.email)) {
errors.email = 'Please enter a valid email';
}
return {
isValid: Object.keys(errors).length === 0,
errors
};
}
React Error Boundaries
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
logError(error, info);
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
Standards Reference
See detailed patterns in:
/standards/global/error-handling.md
Red Flags to Call Out
| Flag | Question to Ask |
|---|---|
| Empty catch block | "What happens when this fails?" |
catch (e) { return null } |
"How will the caller know it failed?" |
| No loading state | "What does the user see while waiting?" |
| Technical error shown | "Will the user understand this message?" |
| No finally for cleanup | "Is loading state stuck on error?" |
| console.log instead of error | "How will you find this in production logs?" |