For some other sites I added the missing part of the chain by hand, but feel that is not the correct solution. What can I do to prevent this error in a more robust way?
Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. crt.sh | example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.
My domain is:
adm-oldenhage.nl
My web server is (include version):
Apache/2.4.56 (Debian)
The operating system my web server runs on is (include version):
Debian 11.8
I can login to a root shell on my machine (yes or no, or I don't know):
yes
I'm using a control panel to manage my site (no, or provide the name and version of the control panel):
No
True, and this is since feb. 8th. Before this date the certificate chain request at letsencrypt gave the full chain including the R3 intermediate. But now the R3 is left away, and only the certificate itself is returned upon requesting a chain. I don't know if this has to do with the policy change since feb 8th, and if manually adding the R3 intermediate might give problems after September 30th.
This is the log. This exact sequence used to give both the certificate and the R3 intermediate up to feb 8th. After that it only gave the certificate without the R3.
Thanks, I see what you mean. Must be something like a timing-issue in the client then, maybe requesting the cert to soon. I will investigate. The behaviour definitely (reproducibly) changed since feb 8th.
At least I'm glad that the intermediate is still delivered, thanks!
I'm curious to hear what the problem was exactly. Because "timing issue" sounds a little bit strange to me: an ACME client would always retrieve that /acme/cert/ path for the certificate and Let's Encrypt always includes the entire chain: there's no way in the ACME protocol to download just the end leaf certificate or just the chain.
It was not a timing issue, but @orangepizza was right all the time. Before feb 8th LetsEncrypt sent 3 certs in the chain, presumably the X3/X1 compatibility cert. The code I used removed that one, i.e. the last one.
I didn't realise that that could be something in the code. After feb 8th, the chain consists of 2 certs, and the code still removed the last one, leaving an incomplete chain.
So to the contrary to what I thought at the moment, the second reply of @orangepizza really hit the mark.
It's probably a good idea to make your client implementation future proof by planning for change: things can always change suddenly, so everything should not require manual intervention.