{"record":{"id":"016f1ca8010f6132","repo":"anomalyco/sst","slug":"cloudflare-api-error-s","errorCode":null,"errorMessage":"Cloudflare API error: %s","messagePattern":"Cloudflare API error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/server/resource/cloudflare-dns-record.go","lineNumber":174,"sourceCode":"\tif resp.StatusCode < 200 || resp.StatusCode >= 300 || !apiResponse.Success {\n\t\t// Check for \"already exists\" in error messages\n\t\tif len(apiResponse.Errors) > 0 {\n\t\t\tfor _, cfError := range apiResponse.Errors {\n\t\t\t\t// Check if message contains \"already exists\" regardless of error code\n\t\t\t\tif strings.Contains(strings.ToLower(cfError.Message), \"already exists\") {\n\t\t\t\t\treturn \"existing-record\", nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// If not an \"already exists\" error, return the error information\n\t\terrorMsgs := []string{}\n\t\tfor _, cfError := range apiResponse.Errors {\n\t\t\terrorMsgs = append(errorMsgs, fmt.Sprintf(\"%s\", cfError.Message))\n\t\t}\n\t\t\n\t\tif len(errorMsgs) > 0 {\n\t\t\treturn \"\", fmt.Errorf(\"Cloudflare API error: %s\", strings.Join(errorMsgs, \"; \"))\n\t\t}\n\t\t\n\t\t// If we couldn't determine a specific error, return the raw response\n\t\treturn \"\", fmt.Errorf(\"failed to create DNS record, status: %d, response: %s\", resp.StatusCode, string(body))\n\t}\n\t\n\t// Success - return the record ID\n\treturn apiResponse.Result.Id, nil\n}","sourceCodeStart":156,"sourceCodeEnd":183,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/server/resource/cloudflare-dns-record.go#L156-L183","documentation":"This error aggregates the message fields of the errors array returned by the Cloudflare API when the DNS record create/update request fails (non-2xx status or success:false). The library joins all error messages with \"; \" so the developer sees exactly what Cloudflare rejected. Note that \"already exists\" errors are intercepted earlier and silently return \"existing-record\".","triggerScenarios":"Cloudflare responds success:false (or non-2xx) with a populated errors array — e.g. invalid record content (code 1004), invalid DNS record type/value mismatch, DNS validation errors, zone not found (code 7003), authentication error (code 9109), or record names exceeding limits.","commonSituations":"Passing a CNAME name that collides with an existing record; an A/AAAA record with a hostname as content; using an API token without DNS edit permission for the zone; wrong zone_id in the URL; CAA/SRV records missing required fields (the special-cased payload path).","solutions":["Read the joined message(s) in the error — they name the exact Cloudflare error code and cause","Verify the API token has Zone.DNS Edit permission for the target zone","Confirm the zone_id in the request URL matches the zone owning the record name","Fix the record payload: content must match the type (e.g. an IP for A records, a hostname for CNAME)","Resolve naming conflicts — CNAME cannot coexist with other records at the same name"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// validate record shape before calling the API\nfunc validateRecord(recType, name, value string) error {\n    switch recType {\n    case \"A\":\n        ip := net.ParseIP(value)\n        if ip == nil || ip.To4() == nil {\n            return fmt.Errorf(\"A record content must be an IPv4 address, got %q\", value)\n        }\n    case \"AAAA\":\n        ip := net.ParseIP(value)\n        if ip == nil || ip.To4() != nil {\n            return fmt.Errorf(\"AAAA record content must be an IPv6 address, got %q\", value)\n        }\n    }\n    return nil\n}","typeGuard":"func isCloudflareAPIError(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"Cloudflare API error:\")\n}","tryCatchPattern":"_, err := record.Create(input, &out)\nif err != nil {\n    if strings.Contains(err.Error(), \"already exists\") {\n        return nil // idempotent\n    }\n    if isCloudflareAPIError(err) {\n        return fmt.Errorf(\"cloudflare rejected the record: %w\", err)\n    }\n    return err\n}","preventionTips":["Ensure record content matches its type (IP for A/AAAA, hostname for CNAME)","Verify the token has Zone.DNS Edit on the target zone before deploy","Check for conflicting records at the same name (CNAME exclusivity)","Confirm the zone_id belongs to the account/zone of the record name"],"tags":["cloudflare","dns","api-error","validation"],"backgroundTag":"cloudflare-api-error","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}