RedisのINCR・DECRコマンドで発生する「ERR value is not an integer or out of range」エラーの修正方法

beginner🔴 Redis2026-05-13| Redis 6.x / 7.x(Linux、macOS、Windows WSL2)— redis-cli、ioredis、redis-py、Jedis、go-redisなど全クライアントライブラリに影響

Error Message

ERR value is not an integer or out of range
#redis#incr#decr#データ型#整数

何が起きたのか?

INCRINCRBYDECR、または DECRBY コマンドを実行したところ、Redisが以下のエラーを返しました:

(error) ERR value is not an integer or out of range

Redisのカウンターコマンドは、保存された値が純粋な10進数の整数のように見える場合にのみ動作します。浮動小数点数、JSONブロブ、空文字列は使用できません。そのキーに他の値が格納された瞬間、コマンドは即座に失敗します。

30秒でエラーを再現する

# Store a float
127.0.0.1:6379> SET page_views 3.5
OK
127.0.0.1:6379> INCR page_views
(error) ERR value is not an integer or out of range

# Store a string
127.0.0.1:6379> SET page_views "hello"
OK
127.0.0.1:6379> INCR page_views
(error) ERR value is not an integer or out of range

# Store an empty string
127.0.0.1:6379> SET page_views ""
OK
127.0.0.1:6379> INCR page_views
(error) ERR value is not an integer or out of range

# Integer too large for 64-bit signed range
127.0.0.1:6379> SET big_num 9999999999999999999999
OK
127.0.0.1:6379> INCR big_num
(error) ERR value is not an integer or out of range

まずキーを診断する

何も変更せずに、まず正確に何が格納されているかを確認しましょう:

127.0.0.1:6379> TYPE your_key
string
127.0.0.1:6379> GET your_key
"3.5"
127.0.0.1:6379> STRLEN your_key
(integer) 3

よくある原因は以下の通りです:

  • "1.0""0.5" のような浮動小数点数 — アプリケーションコードが小数部を切り捨てずに数値をシリアライズした
  • "{\"count\": 1}" のようなJSONブロブ — 整数フィールドを抽出せずにオブジェクト全体を保存した
  • 空文字列 "" — キーが値なしで初期化された
  • 符号付き64ビット範囲(-92233720368547758089223372036854775807)を超えた数値
  • 古いデータモデルから残った古いキーが、カウンターとして再利用されている

クイックフィックス:キーを有効な整数にリセットする

すぐにカウンターを動作させる必要がありますか?上書きしてください:

# Check current value
127.0.0.1:6379> GET page_views
"3.5"

# Overwrite with the closest integer
127.0.0.1:6379> SET page_views 3
OK

# Now INCR works
127.0.0.1:6379> INCR page_views
(integer) 4

ゼロから始める場合は、キーを削除して INCR を直接呼び出すだけです。Redisは存在しないキーをインクリメント前に 0 に初期化します:

127.0.0.1:6379> DEL page_views
(integer) 1
127.0.0.1:6379> INCR page_views
(integer) 1

アプリケーションコードの根本原因を修正する

ケース1:コードが整数の代わりに浮動小数点数を書き込んでいる

浮動小数点数が最も頻繁な原因です。Python、JavaScript、その他いくつかの言語では、1 のような数値を警告なしに "1.0" としてシリアライズすることがあります。そしてRedisはそれをインクリメントすることを拒否します。

# Python — wrong
import redis
r = redis.Redis()
r.set('page_views', 1.0)   # Stores "1.0", not "1"
r.incr('page_views')        # Boom

# Python — correct
r.set('page_views', int(1.0))   # Stores "1"
r.incr('page_views')             # Works
// Node.js (ioredis) — wrong
await redis.set('page_views', parseFloat('3.5'));  // Stores "3.5"

// Node.js — correct
await redis.set('page_views', Math.floor(3.5));   // Stores "3"
await redis.incr('page_views');                    // Works

ケース2:JSONオブジェクトを保存してその中のフィールドをインクリメントしようとしている

Redis文字列は部分的な更新をサポートしていません。カウンターを別のハッシュフィールドとして保存し、代わりに HINCRBY を使用してください:

# Store each field separately as a hash
127.0.0.1:6379> HSET user:42 page_views 10 login_count 3
(integer) 2

# Increment one field atomically
127.0.0.1:6379> HINCRBY user:42 page_views 1
(integer) 11

# Decrement
127.0.0.1:6379> HINCRBY user:42 login_count -1
(integer) 2

ケース3:浮動小数点カウンター — 代わりにINCRBYFLOATを使用する

スコア、レート、または小数点精度が必要な値を追跡しますか?INCRBYFLOAT を使用してください。保存される値は依然として数値である必要がありますが、小数は問題ありません:

127.0.0.1:6379> SET score 10.5
OK
127.0.0.1:6379> INCRBYFLOAT score 0.5
"11"
127.0.0.1:6379> INCRBYFLOAT score 1.25
"12.25"

注意点が一つあります:INCRBYFLOAT を何度も呼び出すと、保存された値に小数点が含まれるようになります。後でそのキーに対して通常の INCR を実行すると失敗します。浮動小数点キーと整数キーは分けて管理してください。

ケース4:キー初期化の競合状態

2つのプロセスが同時に同じキーを初期化しようとするのは典型的な競合です。一方が非整数値を書き込み、もう一方が即座に INCR を呼び出してエラーになります。解決策はシンプルです — 初期化は INCR 自身に任せてください:

# Don't do this (race condition)
IF key not exists:
    SET counter 0
INCR counter

# Do this instead — INCR is atomic and initializes from 0 if key is missing
INCR counter

修正を確認する

# Check the value is a valid integer string
127.0.0.1:6379> GET page_views
"4"

# INCR should return the next integer
127.0.0.1:6379> INCR page_views
(integer) 5

# DECR should work too
127.0.0.1:6379> DECR page_views
(integer) 4

# INCRBY and DECRBY with step
127.0.0.1:6379> INCRBY page_views 10
(integer) 14
127.0.0.1:6379> DECRBY page_views 3
(integer) 11

4つ全てがエラーなく動作しますか?キーは正常です。

インクリメント前にコードにガードを追加する

本番環境のカウンターには安全策が必要です。このPythonヘルパーは、まず保存された値を検証し、破損していればリセットして、発生したことがわかるように警告をログに記録します:

# Python helper
def safe_incr(r, key):
    val = r.get(key)
    if val is not None:
        try:
            int(val)  # Will raise if not a valid integer string
        except (ValueError, TypeError):
            # Reset to 0 and log a warning
            r.set(key, 0)
            print(f"WARNING: reset corrupt counter key '{key}' (was: {val})")
    return r.incr(key)

クイックリファレンス:影響を受けるコマンド

  • INCR key — 1増加させる
  • INCRBY key amount — 指定量増加させる(整数)
  • DECR key — 1減少させる
  • DECRBY key amount — 指定量減少させる(整数)

4つ全てのコマンドは、値が符号付き64ビット整数の文字列表現である必要があります。INCRBYFLOAT は唯一の例外で小数を受け付けますが、同じキーに対して整数コマンドと混在させると、最終的に再びこのエラーに戻ってきます。

Related Error Notes