MeWrite Docs

Elixir: KeyError

Elixirでマップに存在しないキーにアクセスした場合のエラー

概要

Elixirでマップやキーワードリストに存在しないキーにアクセスしようとした場合に発生するエラーです。

エラーメッセージ

** (KeyError) key :name not found in: %{id: 1, email: "test@example.com"}

原因

  1. 存在しないキーへのアクセス: map.keyでアクセスしたがキーがない
  2. タイポ: キー名のスペルミス
  3. データ構造の変更: APIレスポンスやDBスキーマの変更
  4. nil のマップアクセス: nilに対してキーアクセス

解決策

1. Map.get/3 を使用

1
2
3
4
5
6
# 悪い例
user = %{id: 1}
user.name  # KeyError

# 良い例:デフォルト値付き
name = Map.get(user, :name, "Unknown")

2. アクセス構文 [] を使用

1
2
3
4
5
6
# map.key は KeyError を発生させる
user = %{id: 1}
user.name  # KeyError!

# [] はnilを返す
user[:name]  # => nil

3. Map.fetch/2 で明示的にハンドル

1
2
3
4
case Map.fetch(user, :name) do
  {:ok, name} -> "Name: #{name}"
  :error -> "Name not found"
end

4. パターンマッチで安全に抽出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# デフォルト値付きのパターンマッチ
def get_name(%{name: name}), do: name
def get_name(_), do: "Unknown"

# または with 構文
with {:ok, name} <- Map.fetch(user, :name) do
  process_name(name)
else
  :error -> {:error, :name_not_found}
end

5. get_in/2 でネストしたアクセス

1
2
3
4
5
6
7
8
# 悪い例
data.user.profile.name  # 途中でnilならKeyError

# 良い例
get_in(data, [:user, :profile, :name])  # nilを安全に返す

# Access.key/2 でデフォルト値
get_in(data, [Access.key(:user, %{}), Access.key(:profile, %{}), :name])

6. struct でキーを保証

1
2
3
4
5
6
7
8
defmodule User do
  defstruct [:id, :name, :email]
end

# structはすべてのキーが存在することを保証
user = %User{id: 1, name: "John"}
user.name  # => "John"
user.email  # => nil(KeyErrorにならない)

7. キーの存在確認

1
2
3
4
5
if Map.has_key?(user, :name) do
  user.name
else
  "Unknown"
end

8. update系関数での対処

1
2
3
4
5
6
7
8
# 悪い例:キーがないとエラー
Map.update!(user, :count, &(&1 + 1))  # KeyError

# 良い例:デフォルト値付き
Map.update(user, :count, 1, &(&1 + 1))

# または put_new
Map.put_new(user, :count, 0)

9. キーワードリストの場合

1
2
3
4
5
6
7
8
opts = [timeout: 5000]

# 悪い例
opts[:retries]  # => nil(これはOK)
Keyword.fetch!(opts, :retries)  # KeyError

# 良い例
Keyword.get(opts, :retries, 3)  # デフォルト値3

よくある間違い

  • JSONデコード後のマップで文字列キーとアトムキーを混同
  • 外部APIのレスポンス構造の変更を考慮していない
  • nil安全でないパイプライン処理
  • structと通常のマップの挙動の違いを理解していない

Elixir の他のエラー

最終更新: 2025-12-09