PowerDNS-Admin: ValueError: not enough values to unpack (expected 2, got 0)

We are currently using master, so we should have the latest code. Domains with txt record set got 500 error on detail page:

Jul 22 08:22:17 powerdns gunicorn[11437]: ValueError: not enough values to unpack (expected 2, got 0)
Jul 22 08:22:17 powerdns gunicorn[11437]:     r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/powerdnsadmin/models/record.py", line 70, in get_rrsets
Jul 22 08:22:17 powerdns gunicorn[11437]:     rrsets = Record().get_rrsets(domain.name)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/powerdnsadmin/routes/domain.py", line 60, in domain
Jul 22 08:22:17 powerdns gunicorn[11437]:     return f(*args, **kwargs)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/powerdnsadmin/decorators.py", line 60, in decorated_function
Jul 22 08:22:17 powerdns gunicorn[11437]:     return func(*args, **kwargs)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask_login/utils.py", line 261, in decorated_view
Jul 22 08:22:17 powerdns gunicorn[11437]:     return self.view_functions[rule.endpoint](**req.view_args)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
Jul 22 08:22:17 powerdns gunicorn[11437]:     rv = self.dispatch_request()
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
Jul 22 08:22:17 powerdns gunicorn[11437]:     raise value
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
Jul 22 08:22:17 powerdns gunicorn[11437]:     reraise(exc_type, exc_value, tb)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/app.py", line 1820, in handle_user_exception
Jul 22 08:22:17 powerdns gunicorn[11437]:     rv = self.handle_user_exception(e)
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/app.py", line 1951, in full_dispatch_request
Jul 22 08:22:17 powerdns gunicorn[11437]:     response = self.full_dispatch_request()
Jul 22 08:22:17 powerdns gunicorn[11437]:   File "/opt/web/powerdns-admin/flask/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
Jul 22 08:22:17 powerdns gunicorn[11437]: Traceback (most recent call last):
Jul 22 08:22:17 powerdns gunicorn[11437]: [2020-07-22 08:22:17,402] [app.py:1891] ERROR - Exception on /domain/**** [GET]

i already looked into it and this code seems to cause the problem: File /opt/web/powerdns-admin/powerdnsadmin/models/record.py in Line 70

 r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))

If it helps this is what we got from the pdns api (i have removed personal data):

root@powerdns:/opt/web/powerdns-admin/powerdnsadmin# curl -v -H "X-API-Key: ***" http://localhost:8081/api/v1/servers/localhost/zones/*** | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET /api/v1/servers/localhost/zones/*** HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.58.0
> Accept: */*
> X-API-Key: ***
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Connection: close
< Content-Length: 1860
< Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
< Content-Type: application/json
< Server: PowerDNS/4.1.1
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Permitted-Cross-Domain-Policies: none
< X-Xss-Protection: 1; mode=block
<
{ [1860 bytes data]
100  1860  100  1860    0     0   151k      0 --:--:-- --:--:-- --:--:--  151k
* Closing connection 0
{
  "account": "",
  "api_rectify": true,
  "dnssec": true,
  "id": "***.de.",
  "kind": "Master",
  "last_check": 0,
  "masters": [],
  "name": "***",
  "notified_serial": 2020072201,
  "nsec3narrow": false,
  "nsec3param": "",
  "rrsets": [
    {
      "comments": [
        {
          "account": "",
          "content": "",
          "modified_at": 1595405471
        }
      ],
      "name": "***.",
      "records": [],
      "ttl": 0,
      "type": "TXT"
    },
    {
      "comments": [],
      "name": "**.***.de.",
      "records": [
        {
          "content": "xxx.xxx.xxx.xxx",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "A"
    },
    {
      "comments": [],
      "name": "***.***.de.",
      "records": [
        {
          "content": "xxx.xxx.xxx.xxx",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "A"
    },
    {
      "comments": [],
      "name": "***.***.de.",
      "records": [
        {
          "content": "xxx.xxx.xxx.xxx",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "A"
    },
    {
      "comments": [],
      "name": "***.***.de.",
      "records": [
        {
          "content": "xxx.xxx.xxx.xxx",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "A"
    },
    {
      "comments": [],
      "name": "***.",
      "records": [
        {
          "content": "\"v=spf1 a mx -all\"",
          "disabled": false
        }
      ],
      "ttl": 60,
      "type": "TXT"
    },
    {
      "comments": [],
      "name": "***.",
      "records": [
        {
          "content": "***. ***. 2020072201 10800 3600 604800 3600",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "SOA"
    },
    {
      "comments": [],
      "name": "***.",
      "records": [
        {
          "content": "***.",
          "disabled": false
        },
        {
          "content": "***.",
          "disabled": false
        }
      ],
      "ttl": 3600,
      "type": "NS"
    }
  ],
  "serial": 2020072201,
  "soa_edit": "",
  "soa_edit_api": "DEFAULT",
  "url": "/api/v1/servers/localhost/zones/***.de."
}

i am not sure but i think the \" could cause the error.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 26 (3 by maintainers)

Most upvoted comments

I also hit this bug. Noticed that when it happens, there are empty comments stored in the comments mysql table of pdns admin. Deleting those records also servers as a workaround.

Problem for me was, that there were still comments in the comments mysql table of pdns but the records they belonged to where already gone. After deleting the comments in the DB all zones that had comment on non-existing records could be displayed again.

Wrapping a try: except: will solve this issue

diff --git a/powerdnsadmin/models/record.py b/powerdnsadmin/models/record.py
index e0b507c..1296bd4 100644
--- a/powerdnsadmin/models/record.py
+++ b/powerdnsadmin/models/record.py
@@ -67,8 +67,11 @@ class Record(object):
         for r in jdata['rrsets']:
             while len(r['comments'])<len(r['records']):
                 r['comments'].append({"content": "", "account": ""})
-            r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))
-            rrsets.append(r)
+            try:
+                r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))
+                rrsets.append(r)
+            except:
+                pass
 
         return rrsets

quick and dirty fix is to disable the display of comments:

diff --git a/powerdnsadmin/models/record.py b/powerdnsadmin/models/record.py
index 536aa70..f3b22df 100644
--- a/powerdnsadmin/models/record.py
+++ b/powerdnsadmin/models/record.py
@@ -67,7 +67,7 @@ class Record(object):
         for r in jdata['rrsets']:
             while len(r['comments'])<len(r['records']):
                 r['comments'].append({"content": "", "account": ""})
-            r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))
+#            r['records'], r['comments'] = (list(t) for t in zip(*sorted(zip(r['records'], r['comments']), key=by_record_content_pair)))
             rrsets.append(r)

         return rrsets

the comments will be saved, but not shown…

As this seem not to be fixed let me add my observations:

  1. Change “A” record with name docker e.g. TTL field -> save
  2. Change “AAAA” record with name docker e.g. TTL field -> save
  3. Save changes to PDNS

—> Error 500 !!!

Analysing files: Output of API via CURL gives three records, where there should only be two?! The comments for the AAAA record are split in two pieces.

“rrsets”: [ { “comments”: [ { “account”: “”, “content”: “”, “modified_at”: 1598362663 } ], “name”: “docker.”, “records”: [], “ttl”: 0, “type”: “AAAA” }, { “comments”: [], “name”: “docker.”, “records”: [ { “content”: “2a00::1234”, “disabled”: false } ], “ttl”: 1800, “type”: “AAAA” }, { “comments”: [ { “account”: “”, “content”: “”, “modified_at”: 1598362663 } ], “name”: “docker.”, “records”: [ { “content”: “1.2.3.4”, “disabled”: false } ], “ttl”: 1800, “type”: “A” }, …

May this be the error we are looking for.

A fix is easy, “pdnsutil list-zone name.txt”, “pdnsutil del-zone name” and "pdnsutil load-zone name name.txt --> error fixed till next change!!!