{
  "schema_version": 2,
  "id": "operate/rc/changelog/version-release-notes/7-2",
  "title": "Redis 7.2 release notes and breaking changes",
  "url": "https://redis.io/docs/latest/operate/rc/changelog/version-release-notes/7-2/",
  "summary": "Release notes and breaking changes for Redis 7.2 on Redis Cloud.",
  "tags": [
    "docs",
    "operate",
    "rc"
  ],
  "last_updated": "2026-09-25T15:00:13+01:00",
  "page_type": "content",
  "content_hash": "0e34900b1b626b6b2f1c89517376970d94bbd8ba1b1108d47fc3b661132849de",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis 7.2 introduces several changes to existing Redis commands. For more information on the changes in Redis 7.2, see [What's new in Redis 7.2](https://redis.io/docs/latest/develop/whats-new/7-2)."
    },
    {
      "id": "breaking-changes",
      "title": "Breaking changes",
      "role": "content",
      "text": ""
    },
    {
      "id": "redis-72-breaking-changes",
      "title": "Redis 7.2 breaking changes",
      "role": "content",
      "text": "When new major versions of open source Redis change existing commands, upgrading your database to a new version can potentially break some functionality. Before you upgrade, make sure to read the provided list of breaking changes that affect Redis Enterprise and update any applications that connect to your database to handle these changes.\n\nConfirm your Redis database version (`redis_version`) using the admin console or run the following [`INFO`](https://redis.io/docs/latest/commands/info) command via [`redis-cli`](https://redis.io/docs/latest/operate/rs/references/cli-utilities/redis-cli):\n\n[code example]\n\n#### Breaking changes from version 7.0\n\nUpgrading to Redis version 7.2 from version 7.0 introduces the following potentially breaking changes to Redis Enterprise:\n\n##### Programmability\n\n- Time sampling is now frozen during command execution and scripts ([#10300](https://github.com/redis/redis/pull/10300)). While a command or script is running, the keys used by the command or script will not expire. This breaks any script that uses a loop to wait for a key to expire. \n\n- Blocked commands in scripts now work the same way as when they are used in [transactions](https://redis.io/docs/latest/develop/using-commands/transactions) ([#11568](https://github.com/redis/redis/pull/11568)). \n\n##### Error handling\n\n- A blocked stream command that is released when a key no longer exists returns a different error code ([#11012](https://github.com/redis/redis/pull/11012)).\n    - For newly unblocked streams, lists, and zsets, the old implementation returned `UNBLOCKED` when the stream key was deleted or overwritten with a different type. Now, errors will be the same as if the command was processed after the effect.\n\n- ACL errors have been unified across Redis. ([#11160](https://github.com/redis/redis/pull/11160))\n    - When using [RedisModule_Call](https://redis.io/docs/latest/develop/reference/modules/modules-api-ref#redismodule_call) module API function, ACL errors return `-NOPERM` instead of `-ERR`\n\n- [`XREADGROUP`](https://redis.io/docs/latest/commands/xreadgroup) and [`XAUTOCLAIM`](https://redis.io/docs/latest/commands/xautoclaim) create a consumer regardless of whether it was able to perform reading or claiming ([#11012](https://github.com/redis/redis/pull/11012)).\n\n- Any float that is Not a Number will return `nan` ([#11597](https://github.com/redis/redis/pull/11597)).\n\n##### ACLs\n\n- When a blocked client is being unblocked, checks for ACLs and OOM condition checks are now re-evaluated ([#11012](https://github.com/redis/redis/pull/11012)).\n    - If the ACL rules have changed since the command was executed, the command might fail after the client is unblocked.\n\n##### Command introspection, stats, and configuration\n\n- When running [`XINFO CONSUMERS`](https://redis.io/docs/latest/commands/xinfo-consumers), the `idle` time now shows the number of milliseconds that have passed since the last attempted interaction, and the `inactive` time shows the number of milliseconds since the last successful interaction ([#11099](https://github.com/redis/redis/pull/11099))\n    - Previously, `idle` time showed the number of milliseconds that passed since the last successful interaction and there was no `inactive` time.\n\n- Command stats are only updated when the command executes ([#11012](https://github.com/redis/redis/pull/11012)).\n    - Previously, the command stats were updated even if a command was blocked. The command stats are now updated only if and when the command is executed.\n\n#### Breaking changes from version 6.2\n\nUpgrading to open source Redis version 7.2 from version 6.2 introduces the following potentially breaking changes to Redis Enterprise.\n\nAll [breaking changes from version 7.0](#breaking-changes-from-version-70) also apply to Redis version 6.2.\n\n##### Programmability\n\n-  Lua scripts no longer have access to the `print()` function ([#10651](https://github.com/redis/redis/pull/10651)) - The `print`  function was removed from Lua because it can potentially cause the Redis processes to get stuck (if no one reads from stdout). Users should use redis.log. An alternative is to override the  `print`  implementation and print the message to the log file.  \n\n- Block [`PFCOUNT`](https://redis.io/docs/latest/commands/pfcount) and [`PUBLISH`](https://redis.io/docs/latest/commands/publish) in read-only scripts (*_RO commands,  `no-writes`) ([#10744](https://github.com/redis/redis/pull/10744)) - Consider `PFCOUNT` and `PUBLISH` as write commands in scripts, in addition to `EVAL`; meaning:\n  - They can never be used in scripts with shebang (`#!`) and no `no-writes` flag\n  - They are blocked in `EVAL_RO` and `_RO` variants, (even in scripts without shebang (`#!`) flags)\n  - Allow `no-write` scripts in EVAL (not just in EVAL_RO), even during `CLIENT PAUSE WRITE` \n\n- Hide the `may_replicate` flag from the [`COMMAND`](https://redis.io/docs/latest/commands/command) command response  ([#10744](https://github.com/redis/redis/pull/10744)) - As part of the change to treat `may_replicate` commands `PFCOUNT` and `PUBLISH` as write commands in scripts, in addition to `EVAL`, the `may_replicate` flag has been removed from the `COMMAND` response.\n\n##### Error handling\n\n- Rephrased some error responses about invalid commands or arguments ([#10612](https://github.com/redis/redis/pull/10612)) - \n  - Error response for unknown command introduced a case change (`Unknown` to `unknown`)\n  - Errors for module commands extended to cover subcommands, updated syntax to match Redis Server syntax\n  - Arity errors for module commands introduce a case change (`Wrong` to `wrong`); will consider full command name\n\n- Corrected error codes returned from [`EVAL`](https://redis.io/docs/latest/commands/eval) scripts ([#10218](https://github.com/redis/redis/pull/10218), [#10329](https://github.com/redis/redis/pull/10329)). \n\n  These examples show changes in behavior:\n\n  [code example]\n\n- [`ZPOPMIN`](https://redis.io/docs/latest/commands/zpopmin)/[`ZPOPMAX`](https://redis.io/docs/latest/commands/zpopmax) used to produce wrong replies when count is 0 with non-zset  [#9711](https://github.com/redis/redis/pull/9711)):\n  -  `ZPOPMIN`/`ZPOPMAX` used to produce an `(empty array)` when `key` was not a sorted set and the optional `count` argument was set to `0` and now produces a `WRONGTYPE` error response instead.\n  -  The optional `count` argument must be positive. A negative value produces a `value is out of range` error.\n\n  These examples show changes in behavior:\n\n  [code example]\n\n- [`LPOP`](https://redis.io/docs/latest/commands/lpop)/[`RPOP`](https://redis.io/docs/latest/commands/rpop) with count against a nonexistent list returns a null array instead of `(nil)`([#10095](https://github.com/redis/redis/pull/10095)). This change was backported to 6.2.\n\n- [`LPOP`](https://redis.io/docs/latest/commands/lpop)/[`RPOP`](https://redis.io/docs/latest/commands/rpop) used to produce `(nil)` when count is 0, now produces a null array ([#9692](https://github.com/redis/redis/pull/9692)). This change was backported to 6.2.\n\n- [`XCLAIM`](https://redis.io/docs/latest/commands/xclaim)/[`XAUTOCLAIM`](https://redis.io/docs/latest/commands/xautoclaim) skips deleted entries instead of replying with `nil` and deletes them from the pending entry list ([#10227](https://github.com/redis/redis/pull/10227)) - `XCLAIM`/`XAUTOCLAIM` now behaves in the following way:\n  - If you try to claim a deleted entry, it is deleted from the pending entry list (PEL) where it is found (as well as the group PEL). Therefore, such an entry is not claimed, just cleared from PEL (because it doesn't exist in the stream anyway).\n  - Because deleted entries are not claimed, `X[AUTO]CLAIM` does not return \"nil\" instead of an entry.\n  - Added an array of all the deleted stream IDs to `XAUTOCLAIM` response.\n\n#####  ACLs\n\n- [`ACL GETUSER`](https://redis.io/docs/latest/commands/acl-getuser) reply now uses ACL syntax for `keys` and `channels` ([#9974](https://github.com/redis/redis/pull/9974)). `ACL GETUSER` now uses the ACL DSL (Domain Specific Language) for keys and channels. \n\n  These examples show changes in behavior:\n  [code example]\n\n- [`SORT`](https://redis.io/docs/latest/commands/sort)/[`SORT_RO`](https://redis.io/docs/latest/commands/sort_ro) commands reject key access patterns in `GET` and `BY` if the ACL doesn't grant the command full keyspace access ([#10340](https://github.com/redis/redis/pull/10340)) - The `sort` and `sort_ro` commands can access external keys via `GET` and `BY`. In order to make sure the user cannot violate the authorization ACL rules, Redis 7 will reject external keys access patterns unless ACL allows `SORT` full access to all keys.\nFor backwards compatibility, `SORT` with `GET`/`BY` keeps working, but if ACL has restrictions to certain keys, the use of these features will result in a permission denied error.\n\n  These examples show changes in behavior:\n\n  [code example]\n\n  [code example]\n\n  [code example]\n\n  [code example]\n\n- Fix ACL category for [`SELECT`](https://redis.io/docs/latest/commands/select), [`WAIT`](https://redis.io/docs/latest/commands/wait, [`ROLE`](https://redis.io/docs/latest/commands/role, [`LASTSAVE`](https://redis.io/docs/latest/commands/lastsave, [`READONLY`](https://redis.io/docs/latest/commands/readonly, [`READWRITE`](https://redis.io/docs/latest/commands/readwrite, [`ASKING`](https://redis.io/docs/latest/commands/asking) ([#9208](https://github.com/redis/redis/pull/9208)):\n  - `SELECT` and `WAIT` have been recategorized from `@keyspace` to `@connection`  \n  - `ROLE`, `LASTSAVE` have been categorized as  `@admin`  and  `@dangerous`\n  -  `ASKING`, `READONLY`, `READWRITE` have also been assigned the  `@connection`  category and  removed from `@keyspace`\n  - Command categories are explained in [ACL documentation](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl#command-categories)\n\n##### Command introspection, stats, and configuration\n\n- [`COMMAND`](https://redis.io/docs/latest/commands/command) reply drops `random` and `sort-for-scripts` flags, which are now part of [command tips](https://redis.io/docs/latest/develop/reference/command-tips) ([#10104](https://github.com/redis/redis/pull/10104)) - The `random` flag was replaced with the `nondeterministic_output` tip; the `sort-for-scripts` flag was replaced by the ` nondeterministic_output_order` tip\n\n- [`INFO`](https://redis.io/docs/latest/commands/info) `commandstats` now shows the stats per sub-command ([#9504](https://github.com/redis/redis/pull/9504))\nFor example, while previous versions would provide a single entry for all command usage, in Redis 7, each sub command is reported separately:\n\n  - Redis 6.2:\n  \n    [code example]\n\n  - Redis 7:\n  \n    [code example]\n\n- [`CONFIG REWRITE`](https://redis.io/docs/latest/commands/config-rewrite), [`CONFIG RESETSTAT`](https://redis.io/docs/latest/commands/config-resetstat, and most [`CONFIG SET`](https://redis.io/docs/latest/commands/config-setcommands are now allowed during loading ([#9878](https://github.com/redis/redis/pull/9878))"
    },
    {
      "id": "known-limitations",
      "title": "Known limitations",
      "role": "content",
      "text": "There are two known limitations for the version of Redis 7.2 that is packaged with Redis Enterprise.\n\n- Using [`XREADGROUP BLOCK`](https://redis.io/docs/latest/commands/xreadgroup) with `>` to return all new streams will cause the Redis database to freeze until the shard is restarted ([#12031](https://github.com/redis/redis/pull/12301))\n\n- Because a rejected command does not record the duration for command stats, an error will appear after it is reprocessed that will cause the Redis database to freeze until the shard is restarted ([#12247](https://github.com/redis/redis/pull/12247))"
    },
    {
      "id": "migration-guides-for-certain-clients",
      "title": "Migration guides for certain clients",
      "role": "content",
      "text": "If you are using [Go-Redis](https://redis.uptrace.dev/) v9 or [Lettuce](https://redis.github.io/lettuce/) v6+, which by default switch to the RESP3 protocol, and you are running Redis Stack commands, please make sure the protocol version is pinned to RESP2 prior to upgrading to Redis version 7.2.\n\n#### Go-Redis\n\nFor applications using Go-Redis v9 and later, ensure that you have Go-Redis v9.0.5 or newer and pin the protocol version as shown below:\n\n[code example]\n\nNo actions are required for applications using Go-Redis v8 or earlier.\n\n#### Lettuce\n\nTo pin the protocol version, use the snippet below:\n\n[code example]\n\nIf you are using [LettuceMod](https://github.com/redis-developer/lettucemod/), you need to upgrade to [v3.6.0](https://github.com/redis-developer/lettucemod/releases/tag/v3.6.0)."
    }
  ],
  "examples": [
    {
      "id": "redis-72-breaking-changes-ex0",
      "language": "sh",
      "code": "$ redis-cli -p <port> INFO\n\"# Server\nredis_version:7.0.8\n...\"",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex1",
      "language": "diff",
      "code": "1: config set maxmemory 1\n    2: +OK\n    3: eval \"return redis.call('set','x','y')\" 0\n  - 4: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.\n  + 4: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: OOM command not allowed when used memory > 'maxmemory'.\n    5: eval \"return redis.pcall('set','x','y')\" 0\n  - 6: -@user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.\n  + 6: -OOM command not allowed when used memory > 'maxmemory'.\n    7: eval \"return redis.call('select',99)\" 0\n    8: -ERR Error running script (call to 4ad5abfc50bbccb484223905f9a16f09cd043ba8): @user_script:1: ERR DB index is out of range\n    9: eval \"return redis.pcall('select',99)\" 0\n   10: -ERR DB index is out of range\n   11: eval_ro \"return redis.call('set','x','y')\" 0\n  -12: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: Write commands are not allowed from read-only scripts.\n  +12: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: ERR Write commands are not allowed from read-only scripts.\n   13: eval_ro \"return redis.pcall('set','x','y')\" 0\n  -14: -@user_script: 1: Write commands are not allowed from read-only scripts.\n  +14: -ERR Write commands are not allowed from read-only scripts.",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex2",
      "language": "diff",
      "code": "1: zadd myzset 1 \"one\"\n    2: (integer) 1\n    3: zadd myzset 2 \"two\"\n    4: (integer) 1\n    5: zadd myzset 3 \"three\"\n    6: (integer) 1\n    7: zpopmin myzset -1\n  - 8: (empty array)\n  + 8: (error) ERR value is out of range, must be positive\n    9: 127.0.0.1:6379> set foo bar\n   10: OK\n   11: zpopmin foo 0\n  -12: (empty array)\n  +12: (error) WRONGTYPE Operation against a key holding the wrong kind of value",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex3",
      "language": "diff",
      "code": "1: acl setuser foo off resetchannels &channel1 -@all +get\n    2: OK\n    3: acl getuser foo\n    4: 1) \"flags\"\n    5: 2) 1) \"off\"\n    6: 3) \"passwords\"\n    7: 4) (empty array)\n    8: 5) \"commands\"\n    9: 6) \"-@all +get\"\n   10: 7) \"keys\"\n  -11: 8) (empty array)\n  +11: 8) \"\"\n   12: 9)\"channels\"\n  -13 10) 1) \"channel1\"\n  +13 10) \"&channel1\"",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex4",
      "language": "plaintext",
      "code": "USER FOO (+sort ~* ~mylist) \n  #FOO> sort mylist by w* get v*  - is O.K since ~* provides full key access",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex5",
      "language": "plaintext",
      "code": "USER FOO (+sort %R~* ~mylist) \n  #FOO> sort mylist by w* get v*  - is O.K since %R~* provides full key READ access**",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex6",
      "language": "plaintext",
      "code": "USER FOO (+sort %W~* ~mylist)\n  #FOO> sort mylist by w* get v*  - will now fail since $W~* only provides full key WRITE access",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex7",
      "language": "plaintext",
      "code": "USER FOO (+sort ~v* ~mylist)\n  #FOO> sort mylist by w* get v*  - will now fail since ~v* only provides partial key access",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex8",
      "language": "plaintext",
      "code": "cmdstat_acl:calls=4,usec=279,usec_per_call=69.75,rejected_calls=0,failed_calls=2",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "redis-72-breaking-changes-ex9",
      "language": "  ",
      "code": "cmdstat_acl|list:calls=1,usec=4994,usec_per_call=4994.00,rejected_calls=0,failed_calls=0\n    cmdstat_acl|setuser:calls=2,usec=16409,usec_per_call=8204.50,rejected_calls=0,failed_calls=0\n    cmdstat_acl|deluser:calls=1,usec=774,usec_per_call=774.00,rejected_calls=0,failed_calls=0\n    cmdstat_acl|getuser:calls=1,usec=6044,usec_per_call=6044.00,rejected_calls=0,failed_calls=0",
      "section_id": "redis-72-breaking-changes"
    },
    {
      "id": "migration-guides-for-certain-clients-ex0",
      "language": "go",
      "code": "client := redis.NewClient(&redis.Options{\n    Addr:     \"<database_endpoint>\",\n    Protocol: 2, // Pin the protocol version\n})",
      "section_id": "migration-guides-for-certain-clients"
    },
    {
      "id": "migration-guides-for-certain-clients-ex1",
      "language": "java",
      "code": "import io.lettuce.core.*;\nimport io.lettuce.core.api.*;\nimport io.lettuce.core.protocol.ProtocolVersion;\n\n// ...\nRedisClient client = RedisClient.create(\"<database_endpoint>\");\nclient.setOptions(ClientOptions.builder()\n        .protocolVersion(ProtocolVersion.RESP2) // Pin the protocol version \t\n        .build());\n// ...",
      "section_id": "migration-guides-for-certain-clients"
    }
  ]
}
