Dns challenge api error

1. The problem I’m having:

trying to get a dns challenge to work with Spaceship dns provider,
caddy is built with spaceship provider support
tested spaceship api and key/secret work as they should
from log it looks like we present wrong data but cannot see any reference to the spaceship!?
subdomain has its own A-record at spaceship
is there a way to simulate caddy api requests to dns provider somehow to check if it works?

2. Error messages and/or full log output:

```
May 12 21:45:50 debian-12 caddy[1018]: {"level":"error","ts":1778615150.004101,"logger":"tls.obtain","msg":"will retry","error":"[test1.example.com] Obtain: [test1.example.com] solving challenges: presenting for challenge: adding temporary record for zone \"example.com.\": failed to append records: API request failed with status 422: {\"detail\":\"The request is invalid.\",\"data\":[{\"field\":\"items\",\"details\":\"Value is \\\"null\\\" but should be \\\"array\\\".\"}]} (order=https://acme-staging-v02.api.letsencrypt.org/acme/order/291618013/37831845676) (ca=https://acme-staging-v02.api.letsencrypt.org/directory)","attempt":2,"retrying_in":120,"elapsed":63.866788666,"max_duration":2592000}
May 12 21:45:50 debian-12 caddy[1018]: {"level":"error","ts":1778615150.004048,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"test1.example.com","issuer":"acme-v02.api.letsencrypt.org-directory","error":"[test1.example.com] solving challenges: presenting for challenge: adding temporary record for zone \"example.com.\": failed to append records: API request failed with status 422: {\"detail\":\"The request is invalid.\",\"data\":[{\"field\":\"items\",\"details\":\"Value is \\\"null\\\" but should be \\\"array\\\".\"}]} (order=https://acme-staging-v02.api.letsencrypt.org/acme/order/291618013/37831845676) (ca=https://acme-staging-v02.api.letsencrypt.org/directory)"}
May 12 21:45:49 debian-12 caddy[1018]: {"level":"error","ts":1778615149.8381028,"logger":"http.acme_client","msg":"cleaning up solver","identifier":"test1.example.com","challenge_type":"dns-01","error":"no memory of presenting a DNS record for \"_acme-challenge.test1.example.com\" (usually OK if presenting also failed)"}
May 12 21:45:49 debian-12 caddy[1018]: {"level":"info","ts":1778615149.5452263,"logger":"http.acme_client","msg":"trying to solve challenge","identifier":"test1.example.com","challenge_type":"dns-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
May 12 21:45:48 debian-12 caddy[1018]: {"level":"info","ts":1778615148.5488865,"logger":"http","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/291618013","account_contact":["mailto:example@gmail.com"]}
May 12 21:45:48 debian-12 caddy[1018]: {"level":"info","ts":1778615148.5481865,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"test1.example.com"}
May 12 21:44:48 debian-12 caddy[1018]: {"level":"error","ts":1778615088.547588,"logger":"tls.obtain","msg":"will retry","error":"[test1.example.com] Obtain: [test1.example.com] solving challenges: presenting for challenge: adding temporary record for zone \"example.com.\": failed to append records: API request failed with status 422: {\"detail\":\"The request is invalid.\",\"data\":[{\"field\":\"items\",\"details\":\"Value is \\\"null\\\" but should be \\\"array\\\".\"}]} (order=https://acme-v02.api.letsencrypt.org/acme/order/3328493998/510125019106) (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":1,"retrying_in":60,"elapsed":2.410275229,"max_duration":2592000}
May 12 21:44:48 debian-12 caddy[1018]: {"level":"error","ts":1778615088.547514,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"test1.example.com","issuer":"acme-v02.api.letsencrypt.org-directory","error":"[test1.example.com] solving challenges: presenting for challenge: adding temporary record for zone \"example.com.\": failed to append records: API request failed with status 422: {\"detail\":\"The request is invalid.\",\"data\":[{\"field\":\"items\",\"details\":\"Value is \\\"null\\\" but should be \\\"array\\\".\"}]} (order=https://acme-v02.api.letsencrypt.org/acme/order/3328493998/510125019106) (ca=https://acme-v02.api.letsencrypt.org/directory)"}
May 12 21:44:48 debian-12 caddy[1018]: {"level":"error","ts":1778615088.326868,"logger":"http.acme_client","msg":"cleaning up solver","identifier":"test1.example.com","challenge_type":"dns-01","error":"no memory of presenting a DNS record for \"_acme-challenge.test1.example.com\" (usually OK if presenting also failed)"}
May 12 21:44:47 debian-12 caddy[1018]: {"level":"info","ts":1778615087.165243,"logger":"http.acme_client","msg":"trying to solve challenge","identifier":"test1.example.com","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.137891,"logger":"http","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/3328493998","account_contact":["mailto:example@gmail.com"]}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1378338,"logger":"http","msg":"done waiting on internal rate limiter","identifiers":["test1.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":"example@gmail.com"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1377838,"logger":"http","msg":"waiting on internal rate limiter","identifiers":["test1.example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":"example@gmail.com"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1373398,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"test1.example.com"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1372523,"logger":"tls.obtain","msg":"lock acquired","identifier":"test1.example.com"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1278114,"logger":"tls.obtain","msg":"acquiring lock","identifier":"test1.example.com"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1186311,"logger":"tls","msg":"finished cleaning storage units"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1184797,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/var/lib/caddy/.local/share/caddy","instance":"0289b42e-55ef-4743-80ac-9be27d4a88a3","try_again":1778701486.1184788,"try_again_in":86399.99999982}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1178586,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0004ea800"}
May 12 21:44:46 debian-12 caddy[1018]: {"level":"info","ts":1778615086.1044464,"msg":"serving initial configuration"}

```
PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

3. Caddy version:

v2.11.3 h1:/vFbdjcs2DtzcWTIxHybf5R5TspYFFThlZffChyBFHg=

4. How I installed and ran Caddy:

installed by building with xcaddy and run by service
caddy list-modules | grep spaceship
dns.providers.spaceship

a. System environment:

Linux debian-12 6.12.86+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.86-1 (2026-05-08) x86_64 GNU/Linux

b. Command:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

c. Service/unit/compose file:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

d. My complete Caddy config:


test1.example.com:443 {
tls {
dns spaceship {
api_key api-key
api_secret api-secret
}
resolvers 1.1.1.1
}
}

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

5. Links to relevant resources:

This is past the config/env stage. Caddy is reaching the DNS provider path and trying to present the DNS-01 record.

The important part is:

failed to append records: API request failed with status 422

...

"items": "Value is \"null\" but should be \"array\"."

That looks like the Spaceship libdns provider is sending an invalid payload to the Spaceship API probably with items: null instead of an array. So I would treat this as a provider/module issue rather than a Caddyfile or DNS propagation issue.

The cleanup message is expected after the present step fails:

no memory of presenting a DNS record ... usually OK if presenting also failed

I would likely open this against the Spaceship DNS provider repo with this log, your Caddy version, the exact xcaddy build command/module version and the minimal Caddyfile. The useful repro is not whether the Spaceship API key works manually but instead whether the libdns Spaceship provider successfully AppendRecords a TXT record for _acme-challenge.test1.example.com

Hi and thanks for taking the time.

I found this, clearly the same issue I’m facing, very strange when I searched for many different things on the internet prior and none returned the actual github-page.

No need for bug-submission, guess I have some reading to do.

Thanks for pointing me in right direction!!