FreeBSD Certbot: AttributeError: 'Meta' object has no attribute 'profiles'

in FreeBSD


The problem

Requesting a certificate for example.com An unexpected error occurred: AttributeError: 'Meta' object has no attribute 'profiles'

The solution

Upgrade or reinstall py311-acme

Debugging

Check /var/log/letsencrypt/letsencrypt.log for JSON dump of the Directory object:

DEBUG:acme.client:Sending GET request to https://acme-v02.api.letsencrypt.org/directory.
DEBUG:acme.client:Received response:

{
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "profiles": {
      "classic": "https://letsencrypt.org/docs/profiles#classic",
      "shortlived": "https://letsencrypt.org/docs/profiles#shortlived (not yet generally available)",
      "tlsclient": "https://letsencrypt.org/docs/profiles#tlsclient",
      "tlsserver": "https://letsencrypt.org/docs/profiles#tlsserver"
    },
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf",
    "website": "https://letsencrypt.org"
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "renewalInfo": "https://acme-v02.api.letsencrypt.org/acme/renewal-info",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
}

As you can see the profiles are there, yet the code does not see them.

Places to check: /usr/local/lib/python3.11/site-packages/certbot/_internal/client.py

  • print(directory.meta) in create_acme_client() where directory object is introduced
  • print(self.acme.directory.meta) in _get_order_and_authorizations() where the above is simply reused

If you're having this issue, your meta likely looks like this:

Meta(terms_of_service='https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf', website='https://letsencrypt.org', caa_identities=('letsencrypt.org',), external_account_required=None)

So check /usr/local/lib/python3.11/site-packages/acme/messages.py for class Directory -> class Meta -> profiles. Your copy likely does not have that piece.

class Directory(jose.JSONDeSerializable):

    class Meta(jose.JSONObjectWithFields):

        _terms_of_service: str = jose.field('termsOfService', omitempty=True)
        website: str = jose.field('website', omitempty=True)
        caa_identities: List[str] = jose.field('caaIdentities', omitempty=True)
        external_account_required: bool = jose.field('externalAccountRequired', omitempty=True)

        profiles: Dict[str, str] = jose.field('profiles', omitempty=True) # <- THIS
#python #certbot #freebsd