- Python
NoneType object is not subscriptableの直し方
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期連続の黒字決算。