エラーの内容
Redisコマンドを実行すると、サーバーが次のエラーを返します:
(error) ERR unknown command 'COMMAND_NAME', with args beginning with: ...
または短いバリアント:
(error) ERR unknown command 'LMPOP'
Redisはそのコマンドを認識できません。サーバーのバージョンに存在しないか、設定で無効化されているか、またはACLルールによってユーザーへのアクセスが静かにブロックされている可能性があります。
根本原因
- バージョンの不一致 — Redis 6.2または7.xで追加されたコマンドを呼び出しているが、サーバーのバージョンが古い。
- ACL制限 — Redis 6以降のACLルールでは、ユーザーごとに特定のコマンドをブロックできます。このエラーは「コマンドが見つからない」と同じ表示になるため、多くの人が混乱します。
- redis.confのrename-command — コマンドが設定でリネームまたは無効化されており、共有またはマネージドRedisインスタンスでよく見られます。
- モジュール未ロード —
JSON.GET(RedisJSON)などのコマンドは、ロードされていないモジュールを必要とします。 - タイポ — コマンド名の単純なスペルミス。
ステップ1 — Redisのバージョンを確認する
バージョンの不一致が最も一般的な原因です。サーバーで次のコマンドを実行してください:
redis-cli INFO server | grep redis_version
出力例:
redis_version:6.0.16
次に、必要なコマンドが実際にいつ導入されたかを確認します:
LMPOP、ZMPOP— Redis 7.0GETDEL、GETEX— Redis 6.2OBJECT FREQ— Redis 4.0WAIT— Redis 3.0
Redis 6.0を使用してLMPOPを使おうとしていますか?それが問題の原因です。Redisをアップグレードするか、現在のバージョンで動作する同等のコマンドに切り替えてください。
Redisのアップグレード(Ubuntu/Debian)
sudo add-apt-repository ppa:redislabs/redis
sudo apt-get update
sudo apt-get install redis
Redisのアップグレード(macOS)
brew upgrade redis
brew services restart redis
ステップ2 — ACLルールを確認する(Redis 6以降)
Redis 6ではACL(アクセス制御リスト)が追加されました。注意が必要な点は、ACLルールがコマンドをブロックした場合、エラーメッセージが「権限がありません」ではなく「unknown command」と表示されることです。コマンドが存在しないのとまったく同じ見た目になるため、デバッグが本当に難しくなります。
現在のユーザーに許可されている操作を確認します:
redis-cli ACL WHOAMI
redis-cli ACL LIST
制限されたユーザーは次のように表示されます:
"user app on >password ~* &* -@all +get +set +del"
-@allはすべてのコマンドをブロックします。明示的に許可されているのはGET、SET、DELのみです。それ以外のコマンドを呼び出すと「unknown command」エラーが返されます。
修正 — 特定のコマンドを許可する
redis-cli ACL SETUSER app +hset +hget +hgetall
またはカテゴリ全体を許可する — たとえば、すべてのハッシュコマンドを一括で:
redis-cli ACL SETUSER app +@hash
ユーザーにフルアクセスを付与する場合(本番環境では慎重に使用):
redis-cli ACL SETUSER app +@all
ACL変更の永続化
redis-cliで行ったACL変更はメモリ上のみに存在し、再起動すると消えます。保存するには:
redis-cli ACL SAVE
または専用のACLファイルを使ってredis.confに永続的に定義します:
aclfile /etc/redis/users.acl
ステップ3 — redis.confのrename-commandを確認する
ホスティング型Redisプロバイダー(および慎重なシステム管理者)は、FLUSHALLやCONFIGなどの危険なコマンドをrename-commandディレクティブで無効化することがよくあります。これは共有インスタンスでの標準的な慣行です。コマンドが影響を受けているか確認します:
grep -i rename-command /etc/redis/redis.conf
制限されたインスタンスでの典型的な出力:
rename-command FLUSHALL ""
rename-command CONFIG ""
空文字列はコマンドを完全に無効化します。対処法は2つあります:
- 削除ではなくリネームされた場合は、リネーム後のコマンド名を使用する。
rename-commandの行を削除または更新してRedisを再起動する。
設定変更後にRedisを再起動する
# systemd
sudo systemctl restart redis
# macOS
brew services restart redis
ステップ4 — モジュールが必要かどうか確認する
一部のRedisコマンドは、モジュールがロードされている場合にのみ存在します。たとえばJSON.GETはRedisJSONの一部であり、ロードされていないと次のエラーが発生します:
127.0.0.1:6379> JSON.GET mykey
(error) ERR unknown command 'JSON.GET'
サーバーに現在ロードされているモジュールを確認します:
redis-cli MODULE LIST
リストが空、または必要なモジュールが見つからない場合は、redis.confに追加します:
loadmodule /usr/lib/redis/modules/librejson.so
再起動なしでランタイムにロードする場合(一時的 — 再起動後は消えます):
redis-cli MODULE LOAD /path/to/module.so
ステップ5 — タイポを排除する
先に進む前に、簡単なサニティチェックをする価値があります。よくある混同:
SETEXvsSETPX— 一方は秒、もう一方はミリ秒を取るため、簡単に混同するSRANDMEMBER— 頻繁にスペルミスが起きるZADDのNX/XXサブコマンド — Redis 3.0.2以降でのみサポート
Redis自身からコマンドの正確な構文を確認します:
redis-cli COMMAND DOCS ZADD
またはサーバーがサポートするすべてのコマンドを一覧表示します:
redis-cli COMMAND COUNT
redis-cli COMMAND
確認
修正を適用したら、コマンドを直接テストします:
redis-cli -u redis://localhost:6379 LMPOP 1 mylist LEFT
ACL修正の場合は、ユーザーが正しい権限を持っていることを確認します:
redis-cli ACL GETUSER app
コマンドまたはそのカテゴリが、出力のcommandsフィールドに表示されているはずです。
予防策
- Redisのバージョンを固定する — Ansible、Terraform、Dockerイメージタグなどのインフラ設定で固定し、開発環境と本番環境が常に同じバージョンで動作するようにします。環境間のバージョンドリフトが「自分の環境では動く」Redisバグのほとんどの原因です。
- ステージング環境でACLルールを先にテストする。 そこで最小権限のユーザーを作成し、アプリが実際に使用するすべてのコマンドを実行して、本番環境にプッシュする前に何もブロックされていないことを確認します。
- rename-commandのエントリをドキュメント化する。 なぜ
FLUSHALLが存在しないように見えるのか説明するrunbookのメモがなければ、将来のエンジニアが「消えた」コマンドのデバッグに何時間も費やすことになります。 - ローカル開発環境を特定のRedisバージョンに固定する:
docker run --rm redis:7.2 redis-cli --versionで、予期しない問題のないクリーンなバージョン管理された環境が得られます。
Redisの設定ファイルを扱っていますか?ToolCraftのYAML ↔ JSONコンバーターを使えば、デプロイ設定の構文エラーを適用前に検出できます — すべてローカルで動作し、アップロードは一切不要です。

