jeessy2/ddns-go · error

request error: %s

Error message

request error: %s

What it means

dns/spaceship.go request() unmarshals the response into ErrorResponse and returns "request error: %s" with the provider's Detail field whenever the Spaceship API status is neither 200 nor 204. This is the library's wrapper for any non-success Spaceship HTTP response from createRecord, getRecords, or deleteRecords.

Source

Thrown at dns/spaceship.go:104

	}

	type DataItem struct {
		Field   string `json:"field"`
		Details string `json:"details"`
	}

	type ErrorResponse struct {
		Detail string      `json:"detail"`
		Data   *[]DataItem `json:"data,omitempty"`
	}

	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
		var e ErrorResponse
		err = json.Unmarshal(response, &e)
		if err != nil {
			return
		}
		err = fmt.Errorf("request error: %s", e.Detail)
		return
	}

	return
}

func (s *Spaceship) createRecord(recordType string, ip string, domain *config.Domain) (err error) {
	type Item struct {
		Type    string `json:"type"`
		Address string `json:"address"`
		Name    string `json:"name"`
		TTL     int    `json:"ttl"`
	}

	type Payload struct {
		Force bool   `json:"force"`
		Items []Item `json:"items"`
	}

View on GitHub (pinned to 5874c2e666)

Solutions

  1. Read the Detail text embedded in the error — it names the exact API rejection
  2. Verify Spaceship API key and secret are set and not expired
  3. Confirm the domain exists in your Spaceship account
  4. Check record payload fields (type/name/address) against current Spaceship API docs

Example fix

// before
err := provider.createRecord(domain, ip)
// after
if err != nil && strings.Contains(err.Error(), "unauthorized") {
	log.Fatal("check SPACESHIP_API_KEY / SPACESHIP_API_SECRET")
} else if err != nil {
	log.Printf("Spaceship rejected: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

for _, k := range []string{"SPACESHIP_API_KEY", "SPACESHIP_API_SECRET"} {
	if os.Getenv(k) == "" {
		return fmt.Errorf("missing %s", k)
	}
}
if domain.DomainName == "" {
	return errors.New("spaceship: domain required")
}

Type guard

// parse the wrapped Detail for classification
func detailOf(err error) string {
	s := errString(err)
	if strings.HasPrefix(s, "request error: ") {
		return strings.TrimPrefix(s, "request error: ")
	}
	return ""
}

Try / catch

if err != nil {
	switch d := detailOf(err); {
	case strings.Contains(d, "auth") || strings.Contains(d, "key"):
		log.Fatal("spaceship: check API key/secret")
	case strings.Contains(d, "rate"):
		time.Sleep(time.Minute) // back off and retry
	default:
		return err
	}
}

Prevention

When it happens

Trigger: createRecord, getRecords, or deleteRecords calls where the Spaceship API returns 4xx/5xx: invalid API key/secret, unauthenticated request, unknown domain, validation failure on record fields, or rate limiting.

Common situations: Misconfigured SPACESHIP_API_KEY/SECRET; domain not registered in the Spaceship account; sending more records than the API accepts per request; Spaceship API schema changes altering the Detail payload.

Related errors


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