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
- Read the Detail text embedded in the error — it names the exact API rejection
- Verify Spaceship API key and secret are set and not expired
- Confirm the domain exists in your Spaceship account
- 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
- Store Spaceship credentials via env vars, never in code
- Validate the domain exists in the account during setup
- Respect rate limits; add backoff on 429-style Details
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
- API请求失败,状态码: %d, 响应: %s
- Rainyun API error, code=%d
- dnsla 记录列表请求失败,状态码: %d, 响应: %s
- %s
- API请求失败,状态码: %d, 响应: %s
AI-assisted analysis of jeessy2/ddns-go@5874c2e666 (2026-09-03).
Data as JSON: /api/errors/6cff2800ff59de4e.
Report an issue: GitHub.