# Breaking out of a loop early

**URL:** <https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139>\
**Category:** Get Help\
**Tags:** loop\
**Created:** [August 7, 2026, 12:05am UTC](https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139 "2026-08-07T00:05:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Toni](https://avatars.discourse-cdn.com/v4/letter/t/8797f3/32.png) [@Toni](https://forum.ansible.com/u/Toni)\
**Post date:** [August 7, 2026, 12:05am UTC](https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139/1 "2026-08-07T00:05:57Z")

</div>

I want to download a file from a set of URLs in a loop, stopping after the first URL that actually has the file. Here’s a sample playbook illustrating the problem:

```auto
---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: try to get a file
      uri:
        url: "{{ item }}"
        dest: "/tmp/data.dat"
        mode: "0644"
      register: results
      ignore_errors: true
      loop:
        - "http://localhost/readme2.txt"
        - "http://localhost/readme1.txt"
        - "http://localhost/readme.txt"
      loop_control:
        extended: true
      until:
        - results is defined
        - results.results[ansible_loop.index0].status == 200 # <--- This does not work!

    - name: print the results
      debug:
        var: results

```

Of course, the real URLs are different, and the file to be downloaded is pretty big, which is why I would like to avoid doing it N times, but do it only once. With the URLs in the example above, the resulting status codes should be 200, 404, and 200, respectively, so the loop should stop after one iteration. But there’s no guarantee that the first URL will yield a 200, it just so happens to be the case in this test scenario.

I’m struggling with getting the conditions right:

If I leave off the `ignore_errors`, the playbook stops after the loop, and I can’t do any further processing. Also, it still insists on iterating through the list of URLs. If I leave the second condition off, the result looks like this:

```auto
ok: [localhost] => {
    "results": {
        "changed": true,
        "failed": true,
        "msg": "One or more items failed",
        "results": [
            {
                "accept_ranges": "bytes",
                "ansible_loop": {
                    "allitems": [
                        "http://localhost/readme2.txt",
                        "http://localhost/readme1.txt",
                        "http://localhost/readme.txt"
                    ],
                    "first": true,
                    "index": 1,
                    "index0": 0,
                    "last": false,
                    "length": 3,
                    "nextitem": "http://localhost/readme1.txt",
                    "revindex": 3,
                    "revindex0": 2
                },
                "ansible_loop_var": "item",
                ...
                "invocation": {
                    "module_args": {
                        "dest": "/tmp/data.dat",
                        "method": "GET",
                        "path": "/tmp/data.dat",
                        "status_code": [
                            200
                        ],
                        "url": "http://localhost/readme2.txt",
                    }
                },
                "item": "http://localhost/readme2.txt",
                "last_modified": "Mon, 12 Mar 2018 13:58:09 GMT",
                "mode": "0644",
                "msg": "OK (105 bytes)",
                "owner": "toni",
                "path": "/tmp/data.dat",
                "redirected": false,
                "server": "nginx",
                "size": 105,
                "state": "file",
                "status": 200,
                "uid": 1000,
                "url": "http://localhost/readme2.txt"
            },
            {
                "ansible_loop": {
                    "allitems": [
                        "http://localhost/readme2.txt",
                        "http://localhost/readme1.txt",
                        "http://localhost/readme.txt"
                    ],
                    "first": false,
                    "index": 2,
                    "index0": 1,
                    "last": false,
                    "length": 3,
                    "nextitem": "http://localhost/readme.txt",
                    "previtem": "http://localhost/readme2.txt",
                    "revindex": 2,
                    "revindex0": 1
                },
                "ansible_loop_var": "item",
                "invocation": {
                    "module_args": {
                        "method": "GET",
                        "status_code": [
                            200
                        ],
                        "url": "http://localhost/readme1.txt",
                    }
                },
                "item": "http://localhost/readme1.txt",
                "msg": "Status code was 404 and not [200]: HTTP Error 404: Not Found",
                "status": 404,
            },
            {
                "accept_ranges": "bytes",
                "ansible_loop": {
                    "allitems": [
                        "http://localhost/readme2.txt",
                        "http://localhost/readme1.txt",
                        "http://localhost/readme.txt"
                    ],
                    "first": false,
                    "index": 3,
                    "index0": 2,
                    "last": true,
                    "length": 3,
                    "previtem": "http://localhost/readme1.txt",
                    "revindex": 1,
                    "revindex0": 0
                },
                "ansible_loop_var": "item",
                "changed": true,
                "invocation": {
                    "module_args": {
                         "status_code": [
                            200
                        ],
                        "url": "http://localhost/readme.txt",
                        ...
                    }
                },
                "status": 200,
                "url": "http://localhost/readme.txt"
            }
        ],
        "skipped": false
    }
}

```

If I leave the second condition in (`results.results[ansible_loop.index0].status == 200`), I get an error message that I don’t understand:

`"msg": "Task failed: Error while evaluating conditional: object of type 'dict' has no attribute 'results'"`

Is there a way to actually print the state of the variable while in the loop? Because when I redirect the output to file and then process that with `jq`, I get (eg.):

```auto
$ jq '.results.results[1].status' < ansible.json
404

```

I’m running Ansible 2.20.1 from a virtualenv on a Debian 13 machine.

What am I doing wrong, please?

---

<div class="post-metadata">

**Author:** ![flowerysong](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/flowerysong/32/2305_2.png) [@flowerysong](https://forum.ansible.com/u/flowerysong)\
**Post date:** [August 7, 2026, 1:29am UTC](https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139/2 "2026-08-07T01:29:26Z")

</div>

First problem: you are attempting to use the wrong feature; `until` applies to each individual loop item, not to the loop as a whole, so it will retry every single url, not proceed through the list. You should instead be using [`break_when:`](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_loops.html#breaking-out-of-a-loop).

Second problem: while inside a loop the registered variable is just the result for the current item/attempt, not the full aggregated result.

```yaml
    - name: try to get a file
      uri:
        url: "{{ item }}"
        dest: "/tmp/data.dat"
        mode: "0644"
      register: results
      ignore_errors: true
      loop:
        - "http://localhost/readme2.txt"
        - "http://localhost/readme1.txt"
        - "http://localhost/readme.txt"
      loop_control:
        break_when: results.status == 200

```

---

<div class="post-metadata">

**Author:** ![Toni](https://avatars.discourse-cdn.com/v4/letter/t/8797f3/32.png) [@Toni](https://forum.ansible.com/u/Toni)\
**Post date:** [August 7, 2026, 9:42am UTC](https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139/3 "2026-08-07T09:42:43Z")

</div>

Thanks a bunch, works like a charm!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [September 6, 2026, 9:43am UTC](https://forum.ansible.com/t/breaking-out-of-a-loop-early/46139/4 "2026-09-06T09:43:04Z")

</div>

Closed on September 6, 2026, 9:43am UTC

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
