jeessy2/ddns-go · error

invalid response format: missing list field

Error message

invalid response format: missing list field

What it means

When the keyword-query response data is a JSON object, getDomainID expects a 'list' key holding the domain array. If the object has no 'list' field, this error signals the response envelope doesn't match the expected PageResult shape — i.e. the server returned an unrecognized object format.

Solutions

  1. Curl the endpoint and inspect the actual data object keys
  2. Add support for the new shape in getDomainID's switch (e.g. accept v["domains"] or a direct object)
  3. Downgrade/align the DNSMgr server with the API contract this client expects
  4. Check whether the keyword query path /domains?page=1&pageSize=1&keyword=... is still valid in your server version

Example fix

// before (server)
{"code":0,"data":{"domains":[...],"total":1}}
// after (client)
case map[string]interface{}:
    listKey := "list"
    if _, ok := v["list"]; !ok {
        listKey = "domains" // fallback for newer API
    }
    if listData, ok := v[listKey]; ok { ... }
Defensive patterns

Strategy: validation

Validate before calling

// verify the API still returns the expected PageResult envelope
var probe struct {
    Code int             `json:"code"`
    Data json.RawMessage `json:"data"`
}
// GET /api/domains?page=1&pageSize=1 then:
var obj map[string]json.RawMessage
if err := json.Unmarshal(probe.Data, &obj); err != nil {
    return fmt.Errorf("data is not an object")
}
if _, ok := obj["list"]; !ok {
    return fmt.Errorf("API no longer returns 'list' field; client upgrade needed")
}

Type guard

func hasListField(data json.RawMessage) bool {
    var obj map[string]json.RawMessage
    return json.Unmarshal(data, &obj) == nil && obj["list"] != nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "missing list field") {
    log.Printf("DNSMgr response envelope changed; pin server version or upgrade ddns-go: %v", err)
}

Prevention

When it happens

Trigger: GET /domains?page=1&pageSize=1&keyword=<domain> returns data as an object without a 'list' key (e.g. data is the domain object directly, or {domains:[...]}, or an error object inside a code==0 envelope).

Common situations: DNSMgr API version change renaming or nesting the list field; a server that returns the matched domain object directly for keyword searches; misrouted request hitting a different endpoint that returns an object-shaped payload.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — 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/9e6e16a2bf8d9e14. Report an issue: GitHub.

Appendix: source

Thrown at dns/hipmdnsmgr.go:264

	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
		}
	}

	// Method 2: If keyword query not found, use list matching as fallback (compatible with old API)
	// Paginate through all domains to find the target
	const pageSize = 100
	currentPage := 1

	for {

View on GitHub (pinned to 5874c2e666)