anomalyco/sst · error
Cloudflare API error: %s
Error message
Cloudflare API error: %s
What it means
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".
Source
Thrown at pkg/server/resource/cloudflare-dns-record.go:174
if resp.StatusCode < 200 || resp.StatusCode >= 300 || !apiResponse.Success {
// Check for "already exists" in error messages
if len(apiResponse.Errors) > 0 {
for _, cfError := range apiResponse.Errors {
// Check if message contains "already exists" regardless of error code
if strings.Contains(strings.ToLower(cfError.Message), "already exists") {
return "existing-record", nil
}
}
}
// If not an "already exists" error, return the error information
errorMsgs := []string{}
for _, cfError := range apiResponse.Errors {
errorMsgs = append(errorMsgs, fmt.Sprintf("%s", cfError.Message))
}
if len(errorMsgs) > 0 {
return "", fmt.Errorf("Cloudflare API error: %s", strings.Join(errorMsgs, "; "))
}
// If we couldn't determine a specific error, return the raw response
return "", fmt.Errorf("failed to create DNS record, status: %d, response: %s", resp.StatusCode, string(body))
}
// Success - return the record ID
return apiResponse.Result.Id, nil
}View on GitHub (pinned to a0bd20f762)
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
Defensive patterns
Strategy: type-guard
Validate before calling
// validate record shape before calling the API
func validateRecord(recType, name, value string) error {
switch recType {
case "A":
ip := net.ParseIP(value)
if ip == nil || ip.To4() == nil {
return fmt.Errorf("A record content must be an IPv4 address, got %q", value)
}
case "AAAA":
ip := net.ParseIP(value)
if ip == nil || ip.To4() != nil {
return fmt.Errorf("AAAA record content must be an IPv6 address, got %q", value)
}
}
return nil
} Type guard
func isCloudflareAPIError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "Cloudflare API error:")
} Try / catch
_, err := record.Create(input, &out)
if err != nil {
if strings.Contains(err.Error(), "already exists") {
return nil // idempotent
}
if isCloudflareAPIError(err) {
return fmt.Errorf("cloudflare rejected the record: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- The DNS record "${partial.name}" cannot be created because t
- Could not find hosted zone for domain ${inputs.domain}
- The `namespaceId` property must be a positive integer.
- Record name "${recordName}" is not a subdomain of "${domain}
- failed to parse API response: %v
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/016f1ca8010f6132.
Report an issue: GitHub.