はじめに:エラーコード管理は「エラーに“番号付きの名前”を与えること」
業務システムで本気で運用を考え始めると、
「エラーが起きました」だけでは足りなくなります。
どの画面で
どの種類のエラーが
どれくらいの頻度で起きているのか
を、ログや問い合わせ対応の中で素早く共有したくなります。
そこで効いてくるのが エラーコード管理 です。
ざっくり言うと、
「エラーに“人間にも機械にも扱いやすい ID(コード)”を振って、
ログ・画面・マニュアル・問い合わせ対応で共通言語にする」
という仕組みです。
ここでは、初心者向けに
なぜエラーコードが必要なのか
C# でのエラーコード定義パターン(enum/クラス)
例外やログとの紐付け方
小さなユーティリティとしての「エラーコード管理クラス」の形
を、例題付きでかみ砕いて説明します。
なぜエラーコードを管理するのか
「同じエラーを、いつも同じ名前で呼べるようにする」
例えば、ユーザーからこんな問い合わせが来たとします。
「ユーザー登録画面でエラーになりました」
これだけだと、開発側はログを漁りながら「どのエラーだろう…」と探すことになります。
でも、画面にこう出ていたらどうでしょう。
「エラーが発生しました。(エラーコード:USR-001)」
ユーザーが「USR-001」と伝えてくれれば、
開発側はログで「ErrorCode=USR-001」を検索するだけで、
該当するエラーの詳細に一気にたどり着けます。
ここでの重要ポイントは、
エラーコードは「人間同士の会話」と「ログ検索」の両方を楽にするためのラベル
同じ種類のエラーには、常に同じコードを使うことで、知識が蓄積される
ということです。
エラーコードを enum で定義する基本パターン
まずは「意味のある名前」を付けるところから
一番シンプルなやり方は、C# の enum でエラーコードを定義することです。
public enum ErrorCode
{
None = 0,
UserNotFound = 1001,
UserAlreadyExists = 1002,
InvalidInput = 2001,
PermissionDenied = 2002,
DatabaseError = 9001,
ExternalServiceError = 9002
}
C#ここでは、数値はあくまで内部的な ID で、
ログや画面には「数値+シンボリック名」または「シンボリック名だけ」を出すイメージです。
例えば、例外クラスにエラーコードを持たせます。
public class AppException : Exception
{
public ErrorCode ErrorCode { get; }
public AppException(ErrorCode errorCode, string message, Exception? inner = null)
: base(message, inner)
{
ErrorCode = errorCode;
}
}
C#使う側はこうなります。
if (user == null)
{
throw new AppException(
ErrorCode.UserNotFound,
$"ユーザーが見つかりません。Id={id}");
}
C#ここでの重要ポイントは、
エラーコードを enum にすることで、コード補完が効き、タイポを防げる
「どんなエラーがあり得るか」が enum を見れば一覧できる
という点です。
エラーコードとログを紐付ける
ログに必ず「ErrorCode=XXX」を残す
エラーコード管理の真価は、ログと組み合わせたときに発揮されます。
ILogger を使って、エラーコードを必ずログに含めるようにします。
public static class ErrorLoggingExtensions
{
public static void LogError(this ILogger logger, AppException ex, string context)
{
logger.LogError(
ex,
"ErrorCode={ErrorCode} Context={Context} Message={Message}",
ex.ErrorCode,
context,
ex.Message);
}
}
C#使い方はこうです。
try
{
DoSomething();
}
catch (AppException ex)
{
_logger.LogError(ex, "ユーザー登録処理中");
throw;
}
C#ログには、例えばこんな行が残ります。
「ErrorCode=UserNotFound Context=ユーザー登録処理中 Message=ユーザーが見つかりません。Id=123」
ここでの重要ポイントは、
ログに「ErrorCode」というキーで必ず出す
これを軸に検索・集計できるようにする
という設計です。
ログ分析ツール(Elasticsearch、Application Insights など)と組み合わせると、
「UserNotFound がどれくらい発生しているか」といった集計も簡単になります。
エラーコードとユーザー向けメッセージを分離する
「コードは固定」「メッセージは差し替え可能」にしておく
業務システムでは、ユーザー向けメッセージを後から変更したり、多言語対応したりしたくなります。
そのとき、エラーコードとメッセージがベタ書きで結びついていると、変更が大変です。
そこで、「エラーコード → メッセージテンプレート」のマッピングを別に持つパターンがよく使われます。
public static class ErrorMessages
{
private static readonly Dictionary<ErrorCode, string> _messages = new()
{
{ ErrorCode.UserNotFound, "ユーザーが見つかりません。(コード:USR-001)" },
{ ErrorCode.UserAlreadyExists, "同じユーザーが既に存在します。(コード:USR-002)" },
{ ErrorCode.InvalidInput, "入力内容に誤りがあります。(コード:COM-001)" },
{ ErrorCode.PermissionDenied, "この操作を行う権限がありません。(コード:SEC-001)" },
{ ErrorCode.DatabaseError, "システム内部エラーが発生しました。(コード:SYS-DB)" },
{ ErrorCode.ExternalServiceError, "外部サービスとの通信に失敗しました。(コード:SYS-EXT)" }
};
public static string GetMessage(ErrorCode code)
{
if (_messages.TryGetValue(code, out var message))
{
return message;
}
return $"不明なエラーが発生しました。(コード:{code})";
}
}
C#UI 層では、こう使います。
catch (AppException ex)
{
var message = ErrorMessages.GetMessage(ex.ErrorCode);
ShowError(message);
}
C#ここでの重要ポイントは、
エラーコードは変えない(ログや問い合わせのキーになる)
メッセージは別テーブルにしておき、後から差し替えや多言語化ができるようにする
という設計です。
「コードはシステムの約束」「メッセージは人間向けの説明」と割り切ると、整理しやすくなります。
エラーコード管理ユーティリティを作る
「例外生成」「ログ」「ユーザー表示」を一箇所に寄せる
エラーコード管理を本気でやるなら、
「エラーコードを使う場面」をユーティリティに寄せてしまうと、コードがすっきりします。
例えば、こんな小さなヘルパーを考えてみます。
public static class ErrorFactory
{
public static AppException Create(ErrorCode code, string? detail = null, Exception? inner = null)
{
var baseMessage = ErrorMessages.GetMessage(code);
var fullMessage = string.IsNullOrEmpty(detail)
? baseMessage
: $"{baseMessage} 詳細: {detail}";
return new AppException(code, fullMessage, inner);
}
}
C#使う側はこうです。
if (user == null)
{
throw ErrorFactory.Create(
ErrorCode.UserNotFound,
$"Id={id}");
}
C#ログ側は、先ほどの拡張メソッドでエラーコードを必ず出す。
UI 側は、ex.ErrorCode からメッセージを引く。
このように、「エラーコード → 例外 → ログ/画面」の流れを一本のルールにしておくと、
どこから見ても同じエラーコードで追えるようになります。
ここでの重要ポイントは、
エラーコードを「例外」「ログ」「画面表示」の共通キーにする
そのための生成・表示・ログ出力をユーティリティに寄せる
ということです。
実務での運用イメージ:問い合わせ対応と障害調査が楽になる
「エラーコードを言ってもらえれば、すぐログに飛べる」世界
最後に、エラーコード管理が効いてくる具体的な場面をイメージしてみます。
ユーザーが「エラーコード:USR-001 と出ました」と問い合わせてくる
サポート担当がマニュアルで「USR-001=ユーザー未存在」と確認する
開発者はログで「ErrorCode=UserNotFound」を検索し、該当ログをすぐ見つける
必要なら、そのエラーコードの発生回数を集計して、改善優先度を決める
この一連の流れが、「エラーコード」という共通言語でつながります。
ここでの重要ポイントは、
エラーコードは「人間の会話」と「システムのログ」を橋渡しするラベル
だからこそ、適当に増やさず、設計して管理する価値がある
ということです。
まとめ:エラーコード管理は“エラーに名前と住所を与える”設計
エラーコード管理の本質を一言で言うと、
「エラーに一意な名前(コード)と意味を与え、
ログ・画面・マニュアル・問い合わせ対応のすべてで同じ名前で呼べるようにする」
ことです。
押さえておきたいポイントを整理すると、
エラーコードは enum などで定義し、「どんなエラーがあり得るか」を一覧できるようにする。
エラーコードを持つ共通例外クラス(AppException など)を用意し、例外とコードをセットで扱う。
ログには必ず ErrorCode を出力し、検索・集計のキーにする。
ユーザー向けメッセージは「エラーコード → メッセージ」のテーブルで管理し、後から差し替え可能にする。
エラー生成・ログ・表示をユーティリティに寄せて、コード全体のルールを揃える。
ここまでイメージできていれば、
「その場その場で適当にメッセージを投げる」段階から抜けて、
“エラーが整理されていて、追いやすく、運用しやすいシステム”に一歩近づけます。
