jeessy2/ddns-go · error

failed to parse domain list: %w

Error message

failed to parse domain list: %w

What it means

When the keyword-query response data is a JSON array, getDomainID re-marshals it and unmarshals into []DnsMgrDomain; if the array elements don't match the DnsMgrDomain field types (id/account_id/record_count expected numbers; name/third_id strings), this wrapped error is returned.

Source

Thrown at dns/hipmdnsmgr.go:255

	}

	if apiResp.Code != 0 {
		return 0, fmt.Errorf("API error: %s", apiResp.Msg)
	}

	var domains []DnsMgrDomain

	// Smart detection: support both array and object formats
	var rawData interface{}
	if err := json.Unmarshal(apiResp.Data, &rawData); err != nil {
		return 0, fmt.Errorf("failed to parse response data: %w", err)
	}

	switch v := rawData.(type) {
	case []interface{}:
		jsonData, _ := json.Marshal(v)
		if err := json.Unmarshal(jsonData, &domains); err != nil {
			return 0, fmt.Errorf("failed to parse domain list: %w", err)
		}
	case map[string]interface{}:
		if listData, ok := v["list"]; ok {
			jsonData, _ := json.Marshal(listData)
			if err := json.Unmarshal(jsonData, &domains); err != nil {
				return 0, fmt.Errorf("failed to parse domain list: %w", err)
			}
		} else {
			return 0, fmt.Errorf("invalid response format: missing list field")
		}
	default:
		return 0, fmt.Errorf("unknown response data format: %T", rawData)
	}

	// Check if exact match is found
	for _, d := range domains {
		if d.Name == domainName {
			return d.ID, nil

View on GitHub (pinned to 5874c2e666)

Solutions

  1. Curl the endpoint and check the array element types against DnsMgrDomain (numeric id, string name)
  2. If the server returns string IDs, change DnsMgrDomain.ID to json.Number or string and convert
  3. Align the DNSMgr server version with the schema this client expects
  4. Check the wrapped %w message — it names the exact field and Go type mismatch

Example fix

// before (server response)
[{"id":"12","name":"example.com"}]
// after (client fix)
type DnsMgrDomain struct {
    ID json.Number `json:"id"`
    Name string `json:"name"`
    ...
}
Defensive patterns

Strategy: type-guard

Type guard

func isDomainArray(data json.RawMessage) ([]DnsMgrDomain, error) {
    var arr []map[string]interface{}
    if err := json.Unmarshal(data, &arr); err != nil {
        return nil, err
    }
    for _, m := range arr {
        if _, ok := m["id"].(float64); !ok {
            return nil, fmt.Errorf("domain id is not numeric")
        }
        if _, ok := m["name"].(string); !ok {
            return nil, fmt.Errorf("domain name is not a string")
        }
    }
    var domains []DnsMgrDomain
    b, _ := json.Marshal(arr)
    return domains, json.Unmarshal(b, &domains)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to parse domain list") {
    log.Printf("domain schema mismatch; inspect /api/domains item types: %v", err)
    // fall back to manual field mapping via map[string]interface{}
}

Prevention

When it happens

Trigger: The /domains keyword search returns a top-level JSON array whose items have mismatched types, e.g. id as string "12" instead of number, causing json.Unmarshal into []DnsMgrDomain to fail.

Common situations: DNSMgr server version emitting string-typed IDs; a different compatible API (alternate backend) with a slightly different domain schema; custom server forks returning extra/renamed fields with wrong types.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of jeessy2/ddns-go@5874c2e666 (2026-09-03). Data as JSON: /api/errors/38622bf2923f2cea. Report an issue: GitHub.