• システム開発に関わる内容をざっくりと書いていく

C# FormatException / パース失敗の原因と対策

FormatException やパース失敗は、入力文字列と想定フォーマットのズレで起きる。日付・数値・GUID・Enum 変換でよく踏み、ロケールやトリム漏れが原因になりやすい。「例外で落とすか、TryParse で返すか」を先に決める。

先に結論

  • 外部入力は TryParse/モデルバインド検証が基本。Parse 直投げは境界だけ
  • 日付はフォーマットと Culture、数値は桁区切り・小数点に注意
  • 失敗時は「どの項目のどの値か」をログに残す(値のマスクは適切に)
  • API では 400 系で返し、サーバ例外として 500 にしない

よくある原因

  • 空文字・空白・null をそのまま Parse
  • ロケール差分(小数点がカンマ、日付順が違う)
  • ISO 8601 とローカル表記の混在
  • 前後の引用符・BOM・不可視文字
  • Enum 名の大小文字や数値範囲外
  • 複合フォーマット文字列のプレースホルダ不一致(別系統の FormatException)

切り分け

  • スタックトレースで Parse/Convert/バインダのどれかを特定
  • 入力の長さ・Culture・想定フォーマットをログに出す
  • 同じ値を単体テストやスクラッチで TryParse して再現
  • フレームワークのモデル検証エラーと、手書き Parse 例外を混同しない

対策

  • 境界で TryParse。失敗は業務エラーとして返す
  • 日付は DateTimeOffset と不変フォーマット(Invariant/丸め括弧付きフォーマット)を寄せる
  • 数値は Culture を明示。UI 入力と API 入力で方針を分ける
  • 文字列.Format/補間の引数個数不一致もテストで防ぐ

ざっくりまとめ

  • FormatException は入力と想定形式の不一致が本命
  • 外部入力は TryParse+検証。Culture/空白を疑う
  • 失敗は 400 相当で返し、どの項目かを残す

関連記事