> ## Documentation Index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# XCLAIM

> Claim pending messages.

Use `XCLAIM` to change the owner of specific pending entries in a consumer group.

The entries must have been idle for at least `<min-idle-time>` milliseconds, which is what keeps two recovery attempts from stealing the same work from each other: the first claim resets the idle time and the second one then finds nothing to take. Claiming resets the entry's delivery time and increments its delivery counter, unless `JUSTID` is used, which returns only the IDs and leaves the counter alone.

`IDLE` and `TIME` set the new idle time or the last delivery time explicitly, `RETRYCOUNT` overrides the delivery counter, and `FORCE` creates a pending entry for IDs that exist in the stream but are not currently pending. Entries that no longer exist in the stream are removed from the pending list instead of being claimed.

When you want to claim whatever is idle rather than specific IDs, use [`XAUTOCLAIM`](/docs/redis/commands/streams/xautoclaim).

## Syntax

```redis theme={"system"}
XCLAIM <key> <group> <consumer> <min-idle-time> <ID> [<ID> ...]
  [IDLE <ms>]
  [TIME <unix-time-milliseconds>]
  [RETRYCOUNT <count>]
  [FORCE]
  [JUSTID]
  [LASTID <lastid>]
```

## Arguments

| Argument                        | Required | Repeatable | Description                                                                   |
| ------------------------------- | -------- | ---------- | ----------------------------------------------------------------------------- |
| `<key>`                         | Yes      | No         | Redis key targeted by the command.                                            |
| `<group>`                       | Yes      | No         | Consumer group name.                                                          |
| `<consumer>`                    | Yes      | No         | Consumer name within the group.                                               |
| `<min-idle-time>`               | Yes      | No         | Only claim entries that have been idle at least this many milliseconds.       |
| `<ID>`                          | Yes      | Yes        | Stream entry ID.                                                              |
| `IDLE <ms>`                     | No       | No         | Set the entry's idle time to this many milliseconds.                          |
| `TIME <unix-time-milliseconds>` | No       | No         | Set the entry's last-delivery time to this Unix timestamp in milliseconds.    |
| `RETRYCOUNT <count>`            | No       | No         | Set the entry's delivery counter to this value.                               |
| `FORCE`                         | No       | No         | Create the pending entry even when the ID is not in the group's pending list. |
| `JUSTID`                        | No       | No         | Return only entry IDs, without their fields and values.                       |
| `LASTID <lastid>`               | No       | No         | New last-delivered ID for the group.                                          |

## Response

The reply reports the result of the operation. Error replies have the same shape in RESP2 and RESP3 and are surfaced as exceptions by the SDKs below.

| Protocol | Reply                                                |
| -------- | ---------------------------------------------------- |
| RESP2    | Array of entry arrays, or array of IDs with `JUSTID` |
| RESP3    | Array of entry arrays, or array of IDs with `JUSTID` |

<Note>
  Client libraries often decode bulk strings, maps, sets, and numeric strings into language-native values. The table describes the Redis wire reply.
</Note>

## Examples

TCP examples use the TLS `REDIS_URL` from the Upstash console. REST examples use `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN`.

<AccordionGroup>
  <Accordion title="Redis CLI" icon="terminal">
    ```bash theme={"system"}
    XCLAIM my-key workers worker-1 60000 0-0
    ```
  </Accordion>

  <Accordion title="@upstash/redis" icon="node-js" iconType="brands">
    ```ts theme={"system"}
    import { Redis } from "@upstash/redis";

    const redis = Redis.fromEnv();

    const result = await redis.xclaim(
      "mystream",
      "mygroup",
      "consumer1",
      60000,
      ["1638360173533-0", "1638360173533-1"]
    );
    ```
  </Accordion>

  <Accordion title="upstash_redis" icon="python" iconType="brands">
    ```python theme={"system"}
    from upstash_redis import Redis

    redis = Redis.from_env()
    result = redis.xclaim("my-key", "workers", "worker-1", 60000, "0-0")
    print(result)
    ```
  </Accordion>

  <Accordion title="ioredis" icon="node-js" iconType="brands">
    ```ts theme={"system"}
    import Redis from "ioredis";

    const redis = new Redis(process.env.REDIS_URL!);
    const result = await redis.xclaim("my-key", "workers", "worker-1", "60000", "0-0");
    console.log(result);
    ```
  </Accordion>

  <Accordion title="node-redis" icon="node-js" iconType="brands">
    ```ts theme={"system"}
    import { createClient } from "redis";

    const client = await createClient({ url: process.env.REDIS_URL })
      .on("error", console.error)
      .connect();
    const result = await client.xClaim("my-key", "workers", "worker-1", 60000, "0-0");
    console.log(result);
    ```
  </Accordion>

  <Accordion title="redis-py" icon="python" iconType="brands">
    ```python theme={"system"}
    import os
    import redis

    client = redis.from_url(os.environ["REDIS_URL"])
    result = client.xclaim("my-key", "workers", "worker-1", 60000, ["0-0"])
    print(result)
    ```
  </Accordion>

  <Accordion title="go-redis" icon="golang" iconType="brands">
    ```go theme={"system"}
    package main

    import (
        "context"
        "fmt"
        "os"
        "time"

        "github.com/redis/go-redis/v9"
    )

    func main() {
        opts, err := redis.ParseURL(os.Getenv("REDIS_URL"))
        if err != nil {
            panic(err)
        }
        client := redis.NewClient(opts)
        result, err := client.XClaim(context.Background(), &redis.XClaimArgs{Stream: "my-key", Group: "workers", Consumer: "worker-1", MinIdle: time.Minute, Messages: []string{"0-0"}}).Result()
        if err != nil {
            panic(err)
        }
        fmt.Println(result)
    }
    ```
  </Accordion>

  <Accordion title="jedis" icon="java" iconType="brands">
    ```java theme={"system"}
    import java.net.URI;

    import redis.clients.jedis.Jedis;

    try (Jedis jedis = new Jedis(new URI(System.getenv("REDIS_URL")))) {
      Object result = jedis.xclaim("my-key", "workers", "worker-1", 60000, redis.clients.jedis.params.XClaimParams.xClaimParams(), new redis.clients.jedis.StreamEntryID("0-0"));
      System.out.println(result);
    }
    ```
  </Accordion>

  <Accordion title="redis-rs" icon="rust" iconType="brands">
    ```rust theme={"system"}
    use redis::TypedCommands;

    fn main() -> redis::RedisResult<()> {
        let url = std::env::var("REDIS_URL").expect("REDIS_URL is not set");
        let client = redis::Client::open(url)?;
        let mut connection = client.get_connection()?;

        let result = connection.xclaim("my-key", "workers", "worker-1", 60000, &["0-0"])?;
        println!("{result:?}");
        Ok(())
    }
    ```
  </Accordion>
</AccordionGroup>


## Related topics

- [XCLAIM](/docs/redis/sdks/py/commands/stream/xclaim.md)
- [XPENDING](/docs/redis/commands/streams/xpending.md)
- [XAUTOCLAIM](/docs/redis/commands/streams/xautoclaim.md)
- [XGROUP](/docs/redis/commands/streams/xgroup.md)
