"expected string, NoneType found" error when renewing

I’m trying to renew a certificate and I’m getting the following error:

TypeError: sequence item 2: expected string, NoneType found

How should I proceed?

My environment:
CentOS 7, nginx, multiple virtual hosts.
nginx is here: /etc/nginx
The websites are under here: /var/www/html/*

I just rebuilt my server. I was using an old version of letsencrypt on the old server, but when I rebuilt the server I switched to certbot.

I was able to create a new certificate on this new server, but I can’t renew the certs that I created on the previous server.

Note that I am using elastic IP, so the public IP is the same in the old and new servers.

The config file in /etc/letsencrypt/renewal/my-domain.org.conf contains:

# renew_before_expiry = 30 days
version = 0.12.0
archive_dir = /etc/letsencrypt/archive/my-domain.org
cert = /etc/letsencrypt/live/my-domain.org/cert.pem
privkey = /etc/letsencrypt/live/my-domain.org/privkey.pem
chain = /etc/letsencrypt/live/my-domain.org/chain.pem
fullchain = /etc/letsencrypt/live/my-domain.org/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = standalone
installer = None
account = 9999999999999999999999999
$  sudo certbot renew -a nginx --cert-name /etc/letsencrypt/renewal/my-domain.org --dry-run --debug -vvv
Root logging level set at -10
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/my-domain.org.conf
-------------------------------------------------------------------------------
Should renew, less than 30 days before certificate expiry 2017-06-24 18:50:00 UTC.
Cert is due for renewal, auto-renewing...
Requested authenticator nginx and installer None
Single candidate plugin: * nginx
Description: Nginx Web Server plugin - Alpha
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: nginx = certbot_nginx.configurator:NginxConfigurator
Initialized: <certbot_nginx.configurator.NginxConfigurator object at 0x29c2b10>
Prep: True
Selected authenticator <certbot_nginx.configurator.NginxConfigurator object at 0x29c2b10> and installer None
Picked account: <Account(RegistrationResource(body=Registration(status=None, contact=(), agreement=u'https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf', key=JWKRSA(key=<ComparableRSAKey(<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x20bd9d0>)>)), uri=u'https://acme-staging.api.letsencrypt.org/acme/reg/2629245', new_authzr_uri=u'https://acme-staging.api.letsencrypt.org/acme/new-authz', terms_of_service=u'https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf'), a835e03f6ebfc0d90bf7619f71f30fad, Meta(creation_host=u'ip-172-31-62-200.ec2.internal', creation_dt=datetime.datetime(2017, 6, 16, 18, 23, 6, tzinfo=<UTC>)))>
Sending GET request to https://acme-staging.api.letsencrypt.org/directory.
Starting new HTTPS connection (1): acme-staging.api.letsencrypt.org
"GET /directory HTTP/1.1" 200 473
Received response:
HTTP 200
content-length: 473
expires: Sat, 17 Jun 2017 03:24:17 GMT
boulder-request-id: xbe-MdaPkamo3DZGX_krFi4qgoq0CC8MxZcbLLYXTC8
strict-transport-security: max-age=604800
server: nginx
connection: keep-alive
pragma: no-cache
cache-control: max-age=0, no-cache, no-store
date: Sat, 17 Jun 2017 03:24:17 GMT
x-frame-options: DENY
content-type: application/json
replay-nonce: UfwP_X1OX8bMR9M_hTZakg-v5L3aWQdlgh1Ume8kWU8

{
  "IWv7-iKgeVI": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
  "key-change": "https://acme-staging.api.letsencrypt.org/acme/key-change",
  "new-authz": "https://acme-staging.api.letsencrypt.org/acme/new-authz",
  "new-cert": "https://acme-staging.api.letsencrypt.org/acme/new-cert",
  "new-reg": "https://acme-staging.api.letsencrypt.org/acme/new-reg",
  "revoke-cert": "https://acme-staging.api.letsencrypt.org/acme/revoke-cert"
}
Renewing an existing certificate
Requesting fresh nonce
Sending HEAD request to https://acme-staging.api.letsencrypt.org/acme/new-authz.
"HEAD /acme/new-authz HTTP/1.1" 405 0
Received response:
HTTP 405
content-length: 91
pragma: no-cache
boulder-request-id: 3E-HMVyoGCenR6ag7rg-dheqbVYYqTCxg5ZH93OnTW4
expires: Sat, 17 Jun 2017 03:24:17 GMT
server: nginx
connection: keep-alive
allow: POST
cache-control: max-age=0, no-cache, no-store
date: Sat, 17 Jun 2017 03:24:17 GMT
content-type: application/problem+json
replay-nonce: fZO-58widg9onqCcDZEugCoUJ-EKBcQMvSIlr7NjXwc


Storing nonce: fZO-58widg9onqCcDZEugCoUJ-EKBcQMvSIlr7NjXwc
JWS payload:
{
  "identifier": {
    "type": "dns", 
    "value": "my-domain.org"
  }, 
  "resource": "new-authz"
}
Sending POST request to https://acme-staging.api.letsencrypt.org/acme/new-authz:
{
  "header": {
    "alg": "RS256", 
    "jwk": {
      "e": "AQAB", 
      "kty": "RSA", 
      "n": "vkJFYgby66WE29EpDtUQOunSwDg4aRdeul1In-bg-RBokHNwTjPf_0u4OG5rPqaDhZjUa6GkOqc1mUTwUjRGyrO-El5wknxj8NiueKY0TugZFZM6_2tqa3rj2HnoAvi5w6PiFz_42zHNeoED_Q1nMIU3QALUxB6SrIlcIiWMdZY4iP2DneBjauo6590xZ9M1rhmchPJ87sp0STO1XuF7V4k3qeVxurcKVJ6DS9a8g9uoICBNgTKGT5T_UPmfzonrT-9hbUzFuWMtzbh_d2cBX68WhWpfaTxtXNFGjtSBp-_cE_Tt3lvyNpCz_bqeuJCoTyBhHJA8bXcr-Zfj2mmQ6w"
    }
  }, 
  "protected": "eyJub25jZSI6ICJmWk8tNTh3aWRnOW9ucUNjRFpFdWdDb1VKLUVLQmNRTXZTSWxyN05qWHdjIn0", 
  "payload": "ewogICJpZGVudGlmaWVyIjogewogICAgInR5cGUiOiAiZG5zIiwgCiAgICAidmFsdWUiOiAidGFkYW1zdmEub3JnIgogIH0sIAogICJyZXNvdXJjZSI6ICJuZXctYXV0aHoiCn0", 
  "signature": "gdbJxZXqukyMKUrg7Xzic3hUvYX64rUmfAx_y_QDzRpWFFaPJUN_pT2awsFOWSxg2nPseS49Kcpf0rNwx9J41i1_DsJ2IuB8QyOaFwWrKQPPcs9_vmlXwixoFv3DjL6kFL-xXa5ZiFN0ATlL_PiUmdGX5t0XUCK7gYN0a-zpTbPwjyUqWiOgCiUFAwfujkAHhQlLCRmLtK0_8x7sUDeMG-TZh6h4EboyKtaHt7OXDjBU814a0GXFo82JOZjK3qaumh1RqvrbF-BU3DSSo4V-KyqFvK1anDvr-fNiG1az7-9h5lPjsObVs9mLCvxAWFYiY9FmOi7zLJhXh9-J_ccW3A"
}
"POST /acme/new-authz HTTP/1.1" 201 1006
Received response:
HTTP 201
content-length: 1006
expires: Sat, 17 Jun 2017 03:24:17 GMT
boulder-request-id: wdSTLeiQ759nE_g7gHfgN7aAh8YZP2jboskiDEacN8w
strict-transport-security: max-age=604800
server: nginx
cache-control: max-age=0, no-cache, no-store
connection: keep-alive
link: <https://acme-staging.api.letsencrypt.org/acme/new-cert>;rel="next"
location: https://acme-staging.api.letsencrypt.org/acme/authz/zPtEj04N-YBAzJWEnYPH5O4xKGWUNFK3TUFrbP32EKg
pragma: no-cache
boulder-requester: 2629245
date: Sat, 17 Jun 2017 03:24:17 GMT
x-frame-options: DENY
content-type: application/json
replay-nonce: IiLGjHAxc56JckGYd7p2ErS7f2cIdTUiofpPUaXOLZw

{
  "identifier": {
    "type": "dns",
    "value": "my-domain.org"
  },
  "status": "pending",
  "expires": "2017-06-24T03:24:17.825786246Z",
  "challenges": [
    {
      "type": "dns-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/zPtEj04N-YBAzJWEnYPH5O4xKGWUNFK3TUFrbP32EKg/44148767",
      "token": "9rjMzLSMs2pKJRzpG_2tlL1UosaoFzpnd03LFzPLp-c"
    },
    {
      "type": "http-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/zPtEj04N-YBAzJWEnYPH5O4xKGWUNFK3TUFrbP32EKg/44148768",
      "token": "KX4_FTnscvRjXNChT8SZvwj-_TLorDAACTSXPQpjOSw"
    },
    {
      "type": "tls-sni-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/zPtEj04N-YBAzJWEnYPH5O4xKGWUNFK3TUFrbP32EKg/44148769",
      "token": "ZjG1RK3nVLxnmFIitQ6xxdf6LwZHoscpqc5r0rSrcpo"
    }
  ],
  "combinations": [
    [
      2
    ],
    [
      1
    ],
    [
      0
    ]
  ]
}
Storing nonce: IiLGjHAxc56JckGYd7p2ErS7f2cIdTUiofpPUaXOLZw
JWS payload:
{
  "identifier": {
    "type": "dns", 
    "value": "www.my-domain.org"
  }, 
  "resource": "new-authz"
}
Sending POST request to https://acme-staging.api.letsencrypt.org/acme/new-authz:
{
  "header": {
    "alg": "RS256", 
    "jwk": {
      "e": "AQAB", 
      "kty": "RSA", 
      "n": "vkJFYgby66WE29EpDtUQOunSwDg4aRdeul1In-bg-RBokHNwTjPf_0u4OG5rPqaDhZjUa6GkOqc1mUTwUjRGyrO-El5wknxj8NiueKY0TugZFZM6_2tqa3rj2HnoAvi5w6PiFz_42zHNeoED_Q1nMIU3QALUxB6SrIlcIiWMdZY4iP2DneBjauo6590xZ9M1rhmchPJ87sp0STO1XuF7V4k3qeVxurcKVJ6DS9a8g9uoICBNgTKGT5T_UPmfzonrT-9hbUzFuWMtzbh_d2cBX68WhWpfaTxtXNFGjtSBp-_cE_Tt3lvyNpCz_bqeuJCoTyBhHJA8bXcr-Zfj2mmQ6w"
    }
  }, 
  "protected": "eyJub25jZSI6ICJJaUxHakhBeGM1Nkpja0dZZDdwMkVyUzdmMmNJZFRVaW9mcFBVYVhPTFp3In0", 
  "payload": "ewogICJpZGVudGlmaWVyIjogewogICAgInR5cGUiOiAiZG5zIiwgCiAgICAidmFsdWUiOiAid3d3LnRhZGFtc3ZhLm9yZyIKICB9LCAKICAicmVzb3VyY2UiOiAibmV3LWF1dGh6Igp9", 
  "signature": "pzPhqHOLB_SnD_173RX5U2LaQITQge-pWhwmchGKEBlVtGTdPb_QywjhEpCSmMxtJDchYRA0V7-4rg51Guy7mLyQzAEwXfydBKqK5DNtzPmCNOfCokPYlP0iisieyamUFsKV7RtnnH6Zy8NSpPiqVlNt3WiKsGmRqwb0ezss9-9PA7z8cdfcgHJUikqs2PwNUqyY39C_wgBRFTuv2UYgaztjbo7yCd1OsXCVo579J6tzLxcJAiy-f7KVXoSFNUaxaDeyX29BynhZi1oHkTpi4VRRtUTE0onuUcDN_UTJSBU7zPVrSbfunpSPibOXEsUwqvTh9lhDhD0B2UFEIdycCg"
}
"POST /acme/new-authz HTTP/1.1" 201 1010
Received response:
HTTP 201
content-length: 1010
expires: Sat, 17 Jun 2017 03:24:17 GMT
boulder-request-id: 2GFVvBOa91VxCiBefeSmGuDLztgPcGzkhvwmy3-Ir6k
strict-transport-security: max-age=604800
server: nginx
cache-control: max-age=0, no-cache, no-store
connection: keep-alive
link: <https://acme-staging.api.letsencrypt.org/acme/new-cert>;rel="next"
location: https://acme-staging.api.letsencrypt.org/acme/authz/z48m1-Ic0dkxBOEq6CGTuUbD3y42yw8OYWSttJuB1iw
pragma: no-cache
boulder-requester: 2629245
date: Sat, 17 Jun 2017 03:24:17 GMT
x-frame-options: DENY
content-type: application/json
replay-nonce: jyCrlU5doHp5qUT3ZKU91AIkIvJgrfO3FOAsIVeyHno

{
  "identifier": {
    "type": "dns",
    "value": "www.my-domain.org"
  },
  "status": "pending",
  "expires": "2017-06-24T03:24:17.923687156Z",
  "challenges": [
    {
      "type": "dns-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/z48m1-Ic0dkxBOEq6CGTuUbD3y42yw8OYWSttJuB1iw/44148770",
      "token": "_5tZAza-dzpd-RRx-3ne-ryyvq7PnwEQs3BC9FaOCgE"
    },
    {
      "type": "http-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/z48m1-Ic0dkxBOEq6CGTuUbD3y42yw8OYWSttJuB1iw/44148771",
      "token": "qt8ilqpwPXWXBYtwETa9w-9UIo5hsV_Fok5xUHc2ef0"
    },
    {
      "type": "tls-sni-01",
      "status": "pending",
      "uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/z48m1-Ic0dkxBOEq6CGTuUbD3y42yw8OYWSttJuB1iw/44148772",
      "token": "HpIoPQaqJBTGODWsAo-4vHdk2jNzHKu8w95wvhx3thM"
    }
  ],
  "combinations": [
    [
      2
    ],
    [
      0
    ],
    [
      1
    ]
  ]
}
Storing nonce: jyCrlU5doHp5qUT3ZKU91AIkIvJgrfO3FOAsIVeyHno
Performing the following challenges:
tls-sni-01 challenge for my-domain.org
tls-sni-01 challenge for www.my-domain.org
Generating key (1024 bits), not saving to file
Creating backup of /etc/nginx/conf.d/[MANY FILES].conf
Encountered exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/certbot/auth_handler.py", line 115, in _solve_challenges
    resp = self.auth.perform(self.achalls)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 805, in perform
    sni_response = chall_doer.perform()
  File "/usr/lib/python2.7/site-packages/certbot_nginx/tls_sni_01.py", line 75, in perform
    self.configurator.save("SNI Challenge", True)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 717, in save
    self.parser.filedump(ext='')
  File "/usr/lib/python2.7/site-packages/certbot_nginx/parser.py", line 239, in filedump
    out = nginxparser.dumps(tree)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 133, in dumps
    return str(RawNginxDumper(blocks.spaced))
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 97, in __str__
    return ''.join(self)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 86, in __iter__
    for line in self.__iter__([parameter]): # negate "for b0 in blocks"
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 93, in __iter__
    yield "".join(item) + semicolon
TypeError: sequence item 2: expected string, NoneType found

Calling registered functions
Cleaning up challenges
Attempting to renew cert from /etc/letsencrypt/renewal/my-domain.org.conf produced an unexpected error: sequence item 2: expected string, NoneType found. Skipping.
Traceback was:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/certbot/renewal.py", line 418, in handle_renewal_request
    main.renew_cert(lineage_config, plugins, renewal_candidate)
  File "/usr/lib/python2.7/site-packages/certbot/main.py", line 640, in renew_cert
    _get_and_save_cert(le_client, config, lineage=lineage)
  File "/usr/lib/python2.7/site-packages/certbot/main.py", line 77, in _get_and_save_cert
    renewal.renew_cert(config, domains, le_client, lineage)
  File "/usr/lib/python2.7/site-packages/certbot/renewal.py", line 296, in renew_cert
    new_certr, new_chain, new_key, _ = le_client.obtain_certificate(domains)
  File "/usr/lib/python2.7/site-packages/certbot/client.py", line 313, in obtain_certificate
    self.config.allow_subset_of_names)
  File "/usr/lib/python2.7/site-packages/certbot/auth_handler.py", line 74, in get_authorizations
    resp = self._solve_challenges()
  File "/usr/lib/python2.7/site-packages/certbot/auth_handler.py", line 115, in _solve_challenges
    resp = self.auth.perform(self.achalls)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 805, in perform
    sni_response = chall_doer.perform()
  File "/usr/lib/python2.7/site-packages/certbot_nginx/tls_sni_01.py", line 75, in perform
    self.configurator.save("SNI Challenge", True)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 717, in save
    self.parser.filedump(ext='')
  File "/usr/lib/python2.7/site-packages/certbot_nginx/parser.py", line 239, in filedump
    out = nginxparser.dumps(tree)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 133, in dumps
    return str(RawNginxDumper(blocks.spaced))
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 97, in __str__
    return ''.join(self)
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 86, in __iter__
    for line in self.__iter__([parameter]): # negate "for b0 in blocks"
  File "/usr/lib/python2.7/site-packages/certbot_nginx/nginxparser.py", line 93, in __iter__
    yield "".join(item) + semicolon
TypeError: sequence item 2: expected string, NoneType found

** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/my-domain.org/fullchain.pem (failure)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
Exiting abnormally:
Traceback (most recent call last):
  File "/bin/certbot", line 9, in <module>
    load_entry_point('certbot==0.14.1', 'console_scripts', 'certbot')()
  File "/usr/lib/python2.7/site-packages/certbot/main.py", line 742, in main
    return config.func(config, plugins)
  File "/usr/lib/python2.7/site-packages/certbot/main.py", line 692, in renew
    renewal.handle_renewal_request(config)
  File "/usr/lib/python2.7/site-packages/certbot/renewal.py", line 435, in handle_renewal_request
    len(renew_failures), len(parse_failures)))
Error: 1 renew failure(s), 0 parse failure(s)
Please see the logfiles in /var/log/letsencrypt for more details.

This is a bug the certbot engineers are working on fixing.

Thanks for the quick reply.

What is a workaround I can use in the meantime? My cert will expire soon.

Can I just remove the old cert and request a new one?

[EDIT] Oh, wait, this only happens in dry run, but it will be successful if I renew for real? I didn’t want to try that in case I mess up the certificate completely.

Although that is extremely unlikely, you could/should always backup/copy the current cert files to a safe folder/site.

I suspect it will fail with the same error and not change/damage anything at all.
If that is the case, you may have to move the certs and re-obtain certs as when new.
[not ideal, but it extends the problem out 90 days]

Just as a follow up, I confirmed that the problem is only on the dry run. The following command successfully updated my cert:

sudo certbot renew -a nginx --cert-name /etc/letsencrypt/renewal/my-domain.org

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