XIU2/CloudflareSpeedTest · error

Failed to create DNSPod record with IPv6.

Error message

Failed to create DNSPod record with IPv6.

What it means

Printed by the CFST DNSPod auto-update bash script when create_dns_record "AAAA" returns an empty string, meaning the DNSPod Record.Create API call (curl POST to https://dnsapi.cn/Record.Create) did not yield a .record.id. The helper pipes the response through jq -r '.record.id', which outputs nothing when curl fails, jq is missing, the JSON is unparsable, or DNSPod returned an error status object instead of a record. The script never inspects .status.code/.status.message, so the real API error (bad token, wrong domain, invalid record line) is silently discarded. Note the inverse bug: on valid JSON without .record.id, jq -r prints the literal string "null", which passes the [ -n ... ] test and masks failures.

Source

Thrown at script/cfst_dnspod.sh:103

if [ -z "$preferred_ipv6" ]; then
  echo "Failed to get the preferred IPv6 address."
else
  echo "BETTER IPv6: $preferred_ipv6"

  # 获取 IPv6 记录 ID
  ipv6_record_id=$(get_record_id "AAAA")

  if [ -n "$ipv6_record_id" ]; then
    # 更新 IPv6 记录
    update_dns_record "$ipv6_record_id" "AAAA" "$preferred_ipv6"
    echo "Updated DNSPod record with IPv6: $preferred_ipv6"
  else
    # 创建 IPv6 记录
    new_ipv6_record_id=$(create_dns_record "AAAA" "$preferred_ipv6")
    if [ -n "$new_ipv6_record_id" ]; then
      echo "Created DNSPod record with IPv6: $preferred_ipv6"
    else
      echo "Failed to create DNSPod record with IPv6."
    fi
  fi
fi

View on GitHub (pinned to 1da0c025d7)

Solutions

  1. Run the API call manually and read the real error: curl -s -X POST -d 'login_token=<token>&format=json&domain=<domain>&sub_domain=<sub>&record_type=AAAA&record_line=默认&value=<ip>' https://dnsapi.cn/Record.Create | jq . — a status.code other than "1" names the problem (token/domain/line).
  2. Verify jq and curl are installed and on PATH (command -v jq curl) before scheduling the script.
  3. Confirm the env vars are exported in the same shell/cron context: echo "${API_TOKEN:+set}" "${DOMAIN:+set}" "${SUB_DOMAIN:+set}".
  4. Fix the null-string bug: treat jq's literal "null" output as failure — if [ -n "$new_ipv6_record_id" ] && [ "$new_ipv6_record_id" != "null" ].
  5. Make create_dns_record surface the status: capture response, check .status.code == "1", and echo .status.message on failure, matching the guard in cfst_dnspod.sh:100-104.

Example fix

# before
new_ipv6_record_id=$(create_dns_record "AAAA" "$preferred_ipv6")
if [ -n "$new_ipv6_record_id" ]; then
  echo "Created DNSPod record with IPv6: $preferred_ipv6"
else
  echo "Failed to create DNSPod record with IPv6."
fi

# after
response=$(curl -s -X POST -d "login_token=$dnspod_token&format=json&domain=$dnspod_domain&sub_domain=$dnspod_record&record_type=AAAA&record_line=默认&value=$preferred_ipv6" "$dnspod_api_url/Record.Create")
status_code=$(echo "$response" | jq -r '.status.code')
if [ "$status_code" = "1" ] && [ -n "$(echo "$response" | jq -r '.record.id')" ]; then
  echo "Created DNSPod record with IPv6: $preferred_ipv6"
else
  echo "Failed to create DNSPod record with IPv6: $(echo "$response" | jq -r '.status | "\(.code) \(.message)"')"
fi
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/bash
# Pre-flight before running the DNSPod update (cfst_dnspod.sh)
for var in API_TOKEN DOMAIN SUB_DOMAIN; do
  if [ -z "${!var}" ]; then
    echo "Missing required env var: $var" >&2; exit 1
  fi
done
for cmd in curl jq ./cfst; do
  command -v "$cmd" >/dev/null 2>&1 || { echo "Missing tool: $cmd" >&2; exit 1; }
done
# Probe credentials with a cheap read-only call; DNSPod returns status.code "1" on success
probe=$(curl -s -X POST -d "login_token=${API_TOKEN}&format=json&domain=${DOMAIN}" https://dnsapi.cn/Record.List)
[ "$(echo "$probe" | jq -r '.status.code')" = "1" ] || {
  echo "DNSPod auth/domain check failed: $(echo "$probe" | jq -r '.status.message')" >&2; exit 1;
}

Try / catch

# Bash has no try/catch; emulate it around the API call and fail loudly
create_dns_record() {
  local response status
  if ! response=$(curl -sS --max-time 30 -X POST \
      -d "login_token=$dnspod_token&format=json&domain=$dnspod_domain&sub_domain=$dnspod_record&record_type=$1&record_line=默认&value=$2" \
      "$dnspod_api_url/Record.Create"); then
    echo "curl error calling Record.Create" >&2; return 1
  fi
  status=$(echo "$response" | jq -r '.status.code')
  if [ "$status" != "1" ]; then
    echo "DNSPod error $status: $(echo "$response" | jq -r '.status.message')" >&2; return 1
  fi
  echo "$response" | jq -r 'if (.record.id // null) then .record.id else empty end'
}

Prevention

When it happens

Trigger: Specifically: (1) API_TOKEN, DOMAIN, or SUB_DOMAIN env vars unset/invalid, so DNSpod answers {"status":{"code":"6"...}} with no record object; (2) jq not installed or not on PATH, so record_id captures only curl output into an empty variable; (3) curl cannot reach dnsapi.cn (network/firewall), response empty; (4) sub_domain contains characters DNSPod rejects for AAAA creation; (5) record_line=默认 gets mangled by a non-UTF-8 locale so the line ID lookup fails; (6) get_record_id's jq expression '.records[]' errored earlier, so an existing record was treated as absent and Record.Create hit a duplicate/forbidden path.

Common situations: Running the script without exporting API_TOKEN/DOMAIN/SUB_DOMAIN first; a revoked or typo'd DNSPod token; deploying to a minimal host (Alpine, BusyBox container) that lacks jq; running the script from a directory where result6.csv was stale so preferred_ipv6 held a non-IPv6 value; locale/encoding drift between the machine that authored the script and the one running it.

Related errors


AI-assisted analysis of XIU2/CloudflareSpeedTest@1da0c025d7 (2026-08-15). Data as JSON: /api/errors/c308911c01aea352. Report an issue: GitHub.