# Getting error "Need 2 values to unpack in for loop; got 1" in defaulttags.py

**URL:** <https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326>\
**Category:** Mystery Errors\
**Created:** [July 27, 2024, 7:57am UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326 "2024-07-27T07:57:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![eliasrudberg](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/eliasrudberg/32/22860_2.png) [@eliasrudberg](https://forum.djangoproject.com/u/eliasrudberg)\
**Post date:** [July 27, 2024, 7:57am UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326/1 "2024-07-27T07:57:37Z")

</div>

Hello,

As a result of some unusual web requests to my webserver I am sometimes getting the following error message from Django:

```auto
Need 2 values to unpack in for loop; got 1. 

```

It comes from the following place in the code in django/template/defaulttags.py inside the render() function in the ForNode class:

```auto
                if unpack:
                    # If there are multiple loop variables, unpack the item into
                    # them.
                    try:
                        len_item = len(item)
                    except TypeError: # not an iterable
                        len_item = 1
                    # Check loop variable count before unpacking
                    if num_loopvars != len_item:
                        raise ValueError(
                            "Need {} values to unpack in for loop; got {}. ".format(
                                num_loopvars, len_item
                            ),
                        )
                    unpacked_vars = dict(zip(self.loopvars, item))

```

After adding a little extra debug output I figured out that the “item” in this case is of type \<class ‘str’\>, so I suppose then that `len_item = len(item)` will give the length of the string, which apparently in this case was only a single character so `len_item` got the value 1, while at the same time `num_loopvars` is 2 which is why the error message says “Need 2 values to unpack in for loop; got 1.”

I am not familiar with the django code and at the moment I don’t understand much what is going on here.

Is it expected that “item” can be a string of length 1, or does that indicate that something went wrong earlier?

Should the code be changed somehow to handle this case better?

Ideas on how to investigate further?

---

<div class="post-metadata">

**Author:** ![maqnius](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/maqnius/32/11108_2.png) [@maqnius](https://forum.djangoproject.com/u/maqnius)\
**Post date:** [July 27, 2024, 10:58am UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326/2 "2024-07-27T10:58:26Z")

</div>

Hey Elias,

looks like you have a for loop like this somewhere in your template code:

```html
{% for x, y in points %}
    There is a point at {{ x }},{{ y }}
{% endfor %}

```

I.e. you are unpacking the iterable (`points`) into two variables (`x`, `y`).

In the code you pasted, it is checked, if in this case `points` can be unpacked into the two variables `x` and `y`. Therefore `points` needs to be iterable (a list, tuple, string…) and it’s items need to be of length 2.

I would advise you to look for a for loop like this, where you unpack into two variables and then check whether it really makes sense to unpack the iterable into two variables under all possible conditions.

Since `item` is a single character in you case, I would guess that the iterable unexpectedly is a single string (an error message or something like that).

E.g. in the example above it would mean, that `points` usually is something like `[(1,2), (3,4)]`, but under some condition `Error: Could not find.. blah blah`.

When iterating over string, we are iterating over it’s characters, so a situation like this would produce your error.

Hope that helps 🙂

Cheers,  
Mark

---

<div class="post-metadata">

**Author:** ![eliasrudberg](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/eliasrudberg/32/22860_2.png) [@eliasrudberg](https://forum.djangoproject.com/u/eliasrudberg)\
**Post date:** [July 28, 2024, 10:40am UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326/3 "2024-07-28T10:40:33Z")

</div>

Hi @maqnius and thanks for answering! Based on your suggestion I investigated some more and found the following:

The website in question uses a template with a for-loop like this:

```
{% for key, value in request.GET.items %}
    [... doing something with key and value here ...]
{% endfor %}

```

That seems to work most of the time, but there is a problem for certain request URLs, specifically the problem appears when the request URL contains “items=” as in the following example:

```
https://example.org/some/path/?items=x

```

I think what happens is that the “`request.GET.items`” (that the template tries to use) that normally exists, in this case gets confused with the “`items`” that comes in from the request URL.

Do you see what I mean, that things can go wrong in that way?

Is Django to blame here because it fails to distinguish between the different “items”, should this be reported as a bug in Django?

Or is the template to blame, and if so, is there a better way to write such a template that would avoid getting into this problem?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [July 28, 2024, 11:19am UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326/4 "2024-07-28T11:19:12Z")

</div>

Welcome @eliasrudberg !

> [@eliasrudberg](#):
>
> Do you see what I mean, that things can go wrong in that way?

Absolutely.

This is not a bug in Django. This would be functioning in the manner that Django is designed and documented at [The Django template language | Django documentation | Django](https://docs.djangoproject.com/en/5.0/ref/templates/language/).

The error here is trying to use a reference in a template without having the view ensure that the context being passed is correct.

Both the template and the view should be corrected here. The view should ensure the right data is put into the context, probably under a different name, and the template should render that data from that name.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [July 30, 2024, 12:06pm UTC](https://forum.djangoproject.com/t/getting-error-need-2-values-to-unpack-in-for-loop-got-1-in-defaulttags-py/33326/5 "2024-07-30T12:06:57Z")

</div>

I think the issue is that in a template the lookup `request.GET.items` will try `request.GET["items"]` before `request.GET.items` per [the variables docs](https://docs.djangoproject.com/en/5.0/ref/templates/language/#variables). So when the key ‘items’ isn’t present, the template works, but once it is, it returns that string instead.

The easiest fix would be to do as Ken suggests and pass an extra context variable, in this case I think something like:

```python
return render(..., context={"query_params": request.GET.items()})

```

Alternatively, try making a custom template tag for whatever manipulation you’re doing with `request.GET`. Perhaps you need something like [`{% querystring %}`](https://docs.djangoproject.com/en/5.1/releases/5.1/#querystring-template-tag), coming in Django 5.1? (Easily copy-pastable into your project on an older version.)
