TypeError: 'NoneType' object is not subscriptable は、None に対して [ ](添字・キー)を使ったときのエラーです。 x["name"] や x[0] の x が、辞書やリストではなく None になっています。

直し方は2つの手順です。

手順 やること
1 どの値が None なのかを特定する(Python 3.11 以降は、トレースバックの ^ の位置で分かる)
2 なぜ None になったのかを直す。「見つからない」がありうる処理なら、if x is None: で分けて扱う

確認環境:Python 3.10・3.11・3.12・3.13、mypy 2.4.0(確認日 2026年10月10日)。以下のエラーはすべて、この4つの版で同じメッセージになりました。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「NoneType object is not subscriptableの直し方」

None になる典型6パターン

# 書き方 None になる理由 直し方
1 find_user(2)["name"] 関数が見つからないときに何も return しない 見つからないときの戻り値を決めて、呼び出し側で判定
2 nums = nums.sort() list.sort() は並べ替えるだけで、None を返す nums.sort() だけにする、または nums = sorted(nums)
3 cfg.get("cache")["ttl"] dict.get はキーが無いと None を返す cfg.get("cache", {})、またはキーの有無を判定
4 re.match(...)[1] 一致しないと None を返す。match は先頭からしか見ない if m is None: で分ける。途中を探すなら re.search
5 cur.fetchone()[0] 0件のとき fetchone() は None を返す 0件のときの扱いを決めて判定
6 data["result"]["items"] JSON の null は None になる API の仕様で null がありうる項目を判定

1. return の無い関数

def find_user(uid):
    users = {1: {"name": "佐藤"}}
    if uid in users:
        return users[uid]
    # 見つからないときは何も return しない → None が返る

print(find_user(2)["name"])
# TypeError: 'NoneType' object is not subscriptable

Python の関数は、return を通らずに終わると None を返します。「見つからない」ときにどうするかを決めます。

def user_name(uid: int) -> str:
    user = find_user(uid)
    if user is None:
        raise LookupError(f"ユーザーが見つかりません: uid={uid}")
    return user["name"]
LookupError: ユーザーが見つかりません: uid=2      ← 原因が分かるエラーになる

2. list.sort() の結果を代入している

nums = [3, 1, 2]
nums = nums.sort()     # sort() はリストそのものを並べ替えて None を返す
print(nums[0])         # TypeError: 'NoneType' object is not subscriptable
書き方 結果
nums.sort() nums そのものが並べ替わる。戻り値は None
nums = sorted(nums) 並べ替えた新しいリストを返す

list.reverse()・list.append()・dict.update() なども、同じく None を返します。

3. dict.get でキーが無い

cfg = {"db": {"host": "localhost"}}
print(cfg.get("cache")["ttl"])     # "cache" が無い → None["ttl"]
ttl = cfg.get("cache", {}).get("ttl", 60)   # 無いときの値を決めておく

4. re.match が一致しない

import re
m = re.match(r"(\d{3})-(\d{4})", "〒060-0001")
print(m[1])     # TypeError: 'NoneType' object is not subscriptable

re.match は文字列の先頭から一致を調べます。 先頭が「〒」なので一致せず、None になりました。途中から探すなら re.search です。どちらも、一致しなければ None を返すので判定します。

def zip_code(text: str) -> str | None:
    m = re.search(r"(\d{3})-(\d{4})", text)
    if m is None:
        return None
    return m[1] + m[2]

print(zip_code("〒060-0001"), zip_code("郵便番号なし"))
# 0600001 None

5. DB の検索が0件

row = cur.execute("SELECT name FROM users WHERE id = ?", (9,)).fetchone()
print(row[0])     # 0件なら row は None
row = cur.execute("SELECT name FROM users WHERE id = ?", (9,)).fetchone()
if row is None:
    ...           # 0件のときの処理
else:
    name = row[0]

6. JSON の null

import json
data = json.loads('{"result": null}')
print(data["result"]["items"])     # null は None になる

API の応答で、エラーのときや0件のときに null が返る項目は、判定してから使います。

どの値が None かを見つける:トレースバックの ^

res["data"]["user"]["address"]["city"] のように1行に何段もあると、どこが None か分かりません。Python 3.11 以降は、トレースバックに印が付きます。

== Python 3.10
    city = res["data"]["user"]["address"]["city"]
TypeError: 'NoneType' object is not subscriptable

== Python 3.13
    city = res["data"]["user"]["address"]["city"]
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable

~~~ の部分(res["data"]["user"])が None で、^^^ の部分(["address"])を使おうとして失敗した、という意味です。この印は Python 3.11 で加わりました(公式の「What's New In Python 3.11」)。3.10 以前では、1段ずつ変数に分けるか、print で確かめます。

似たエラーとの見分け方

None に対して何をしようとしたかで、メッセージが変わります。どれも原因は「None が入っている」で、直し方は同じです。

メッセージ None に対してしたこと
'NoneType' object is not subscriptable x[0]・x["key"](読み取り)
'NoneType' object does not support item assignment x["key"] = 値(書き込み)
'NoneType' object has no attribute 'get' x.get(...) などのメソッド・属性
'NoneType' object is not iterable for v in x:・a, b = x
object of type 'NoneType' has no len() len(x)
unsupported operand type(s) for +: 'NoneType' and 'int' x + 1 などの計算

None の判定は is None で書く

if user is None:     # None かどうか
    ...
if not user:         # None のほか、{}・[]・""・0 も「偽」になる
    ...

bool(0)・bool("")・bool([]) はどれも False です。0件のリストや数値の 0 を「無い」と区別したいときは、if not x: ではなく if x is None: で書きます。

「とりあえず or {} を付けて止める」書き方は、エラーは消えますが、本来は来るはずのデータが来ていない不具合を隠すことがあります。None がありうる仕様なのか、来てはいけないのかを決めてから書きます。

実行する前に見つける:型ヒントと mypy

戻り値が None になりうる関数に型ヒント(-> X | None)を付けておくと、mypy が実行する前に指摘します。

import re

def find_user(uid: int) -> dict[str, str] | None:
    users = {1: {"name": "佐藤"}}
    return users.get(uid)

def zip_code(text: str) -> str:
    m = re.match(r"(\d{3})-(\d{4})", text)
    return m[1] + m[2]

def user_name(uid: int) -> str:
    return find_user(uid)["name"]

def sorted_nums() -> int:
    nums = [3, 1, 2]
    nums = nums.sort()
    return nums[0]
$ mypy typed.py
typed.py:9: error: Value of type "Match[str] | None" is not indexable  [index]
typed.py:12: error: Value of type "dict[str, str] | None" is not indexable  [index]
typed.py:16: error: Incompatible types in assignment (expression has type "None", variable has type "list[int]")  [assignment]
Found 3 errors in 1 file (checked 1 source file)

re.match・自作の関数・list.sort() の3つとも、実行前に見つかりました。 上の「直し方」のように if ... is None: で分けて書き直すと、Success: no issues found になりました。標準ライブラリの re.match や dict.get には、最初から「None を返しうる」型が付いています。

確認の手順(チェックリスト)

順番 確認すること 方法
1 どの値が None か 3.11 以降は ^ の位置。以前の版は1段ずつ変数に分ける
2 その値はどこから来たか 関数の戻り値・get・match・fetchone・JSON
3 = x.sort() のような代入がないか sort・append・reverse・update は None を返す
4 None がありうる仕様か ありうるなら if x is None:、ありえないなら来ない原因を直す
5 再発を防ぐ 型ヒント -> X | None と mypy

よくある質問

Q. try / except TypeError で囲めば直りますか。 A. エラーは止まりますが、None になった原因はそのまま残り、別の場所で同じ問題が起きます。None がありうる場所で if x is None: と判定するほうが、何が起きたかが分かります。

Q. pandas や Django でも出ますか。 A. 出ます。メッセージの意味は同じで、None に [ ] を使っています。トレースバックの最後の自分のコードの行から、None になった値を探します。

まとめ

  • None に [ ] を使ったエラー。どの値が None かを特定して、なぜ None になったかを直す
  • 典型は return の無い関数・x = x.sort()・dict.get・re.match・fetchone() の0件・JSON の null
  • Python 3.11 以降は、トレースバックの ~~~^^^ で None の場所が分かる
  • has no attribute・not iterable・no len() も同じ原因
  • 判定は if x is None:。if not x: は 0 や空のリストも含む
  • 型ヒントと mypy で、実行前に見つけられる

参考・出典

確認日はいずれも 2026年10月10日です。

  • Python ドキュメント「What's New In Python 3.11」(PEP 657: Fine-grained error locations in tracebacks):https://docs.python.org/3/whatsnew/3.11.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「NoneType object is not subscriptableの直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?