{"record":{"id":"c308911c01aea352","repo":"XIU2/CloudflareSpeedTest","slug":"failed-to-create-dnspod-record-with-ipv6","errorCode":null,"errorMessage":"Failed to create DNSPod record with IPv6.","messagePattern":"Failed to create DNSPod record with IPv6\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"script/cfst_dnspod.sh","lineNumber":103,"sourceCode":"if [ -z \"$preferred_ipv6\" ]; then\n  echo \"Failed to get the preferred IPv6 address.\"\nelse\n  echo \"BETTER IPv6: $preferred_ipv6\"\n\n  # 获取 IPv6 记录 ID\n  ipv6_record_id=$(get_record_id \"AAAA\")\n\n  if [ -n \"$ipv6_record_id\" ]; then\n    # 更新 IPv6 记录\n    update_dns_record \"$ipv6_record_id\" \"AAAA\" \"$preferred_ipv6\"\n    echo \"Updated DNSPod record with IPv6: $preferred_ipv6\"\n  else\n    # 创建 IPv6 记录\n    new_ipv6_record_id=$(create_dns_record \"AAAA\" \"$preferred_ipv6\")\n    if [ -n \"$new_ipv6_record_id\" ]; then\n      echo \"Created DNSPod record with IPv6: $preferred_ipv6\"\n    else\n      echo \"Failed to create DNSPod record with IPv6.\"\n    fi\n  fi\nfi\n","sourceCodeStart":85,"sourceCodeEnd":107,"githubUrl":"https://github.com/XIU2/CloudflareSpeedTest/blob/1da0c025d7b6f9bf0b2b0cf47a547f65430deab2/script/cfst_dnspod.sh#L85-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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).","Verify jq and curl are installed and on PATH (command -v jq curl) before scheduling the script.","Confirm the env vars are exported in the same shell/cron context: echo \"${API_TOKEN:+set}\" \"${DOMAIN:+set}\" \"${SUB_DOMAIN:+set}\".","Fix the null-string bug: treat jq's literal \"null\" output as failure — if [ -n \"$new_ipv6_record_id\" ] && [ \"$new_ipv6_record_id\" != \"null\" ].","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."],"exampleFix":"# before\nnew_ipv6_record_id=$(create_dns_record \"AAAA\" \"$preferred_ipv6\")\nif [ -n \"$new_ipv6_record_id\" ]; then\n  echo \"Created DNSPod record with IPv6: $preferred_ipv6\"\nelse\n  echo \"Failed to create DNSPod record with IPv6.\"\nfi\n\n# after\nresponse=$(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\")\nstatus_code=$(echo \"$response\" | jq -r '.status.code')\nif [ \"$status_code\" = \"1\" ] && [ -n \"$(echo \"$response\" | jq -r '.record.id')\" ]; then\n  echo \"Created DNSPod record with IPv6: $preferred_ipv6\"\nelse\n  echo \"Failed to create DNSPod record with IPv6: $(echo \"$response\" | jq -r '.status | \"\\(.code) \\(.message)\"')\"\nfi","handlingStrategy":"validation","validationCode":"#!/bin/bash\n# Pre-flight before running the DNSPod update (cfst_dnspod.sh)\nfor var in API_TOKEN DOMAIN SUB_DOMAIN; do\n  if [ -z \"${!var}\" ]; then\n    echo \"Missing required env var: $var\" >&2; exit 1\n  fi\ndone\nfor cmd in curl jq ./cfst; do\n  command -v \"$cmd\" >/dev/null 2>&1 || { echo \"Missing tool: $cmd\" >&2; exit 1; }\ndone\n# Probe credentials with a cheap read-only call; DNSPod returns status.code \"1\" on success\nprobe=$(curl -s -X POST -d \"login_token=${API_TOKEN}&format=json&domain=${DOMAIN}\" https://dnsapi.cn/Record.List)\n[ \"$(echo \"$probe\" | jq -r '.status.code')\" = \"1\" ] || {\n  echo \"DNSPod auth/domain check failed: $(echo \"$probe\" | jq -r '.status.message')\" >&2; exit 1;\n}","typeGuard":null,"tryCatchPattern":"# Bash has no try/catch; emulate it around the API call and fail loudly\ncreate_dns_record() {\n  local response status\n  if ! response=$(curl -sS --max-time 30 -X POST \\\n      -d \"login_token=$dnspod_token&format=json&domain=$dnspod_domain&sub_domain=$dnspod_record&record_type=$1&record_line=默认&value=$2\" \\\n      \"$dnspod_api_url/Record.Create\"); then\n    echo \"curl error calling Record.Create\" >&2; return 1\n  fi\n  status=$(echo \"$response\" | jq -r '.status.code')\n  if [ \"$status\" != \"1\" ]; then\n    echo \"DNSPod error $status: $(echo \"$response\" | jq -r '.status.message')\" >&2; return 1\n  fi\n  echo \"$response\" | jq -r 'if (.record.id // null) then .record.id else empty end'\n}","preventionTips":["Export API_TOKEN, DOMAIN and SUB_DOMAIN in the cron/systemd unit, not just the interactive shell.","Keep the literal 'null' failure mode out of guards: test [ -n \"$id\" ] && [ \"$id\" != \"null\" ].","Always parse DNSPod .status.code and log .status.message instead of relying on presence of .record.id.","Pin a UTF-8 locale (LC_ALL=C.UTF-8) so record_line=默认 is sent correctly.","Run one manual cfst round plus one manual API round before automating."],"tags":["dnspod","dns","bash","curl","jq","ipv6","ddns"],"backgroundTag":null,"analyzedSha":"1da0c025d7b6f9bf0b2b0cf47a547f65430deab2","analyzedAt":"2026-08-15T22:22:10.737Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}