{"record":{"id":"6cff2800ff59de4e","repo":"jeessy2/ddns-go","slug":"request-error-s","errorCode":null,"errorMessage":"request error: %s","messagePattern":"request error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dns/spaceship.go","lineNumber":104,"sourceCode":"\t}\n\n\ttype DataItem struct {\n\t\tField   string `json:\"field\"`\n\t\tDetails string `json:\"details\"`\n\t}\n\n\ttype ErrorResponse struct {\n\t\tDetail string      `json:\"detail\"`\n\t\tData   *[]DataItem `json:\"data,omitempty\"`\n\t}\n\n\tif resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {\n\t\tvar e ErrorResponse\n\t\terr = json.Unmarshal(response, &e)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\terr = fmt.Errorf(\"request error: %s\", e.Detail)\n\t\treturn\n\t}\n\n\treturn\n}\n\nfunc (s *Spaceship) createRecord(recordType string, ip string, domain *config.Domain) (err error) {\n\ttype Item struct {\n\t\tType    string `json:\"type\"`\n\t\tAddress string `json:\"address\"`\n\t\tName    string `json:\"name\"`\n\t\tTTL     int    `json:\"ttl\"`\n\t}\n\n\ttype Payload struct {\n\t\tForce bool   `json:\"force\"`\n\t\tItems []Item `json:\"items\"`\n\t}","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/dns/spaceship.go#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := provider.createRecord(domain, ip)\n// after\nif err != nil && strings.Contains(err.Error(), \"unauthorized\") {\n\tlog.Fatal(\"check SPACESHIP_API_KEY / SPACESHIP_API_SECRET\")\n} else if err != nil {\n\tlog.Printf(\"Spaceship rejected: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"for _, k := range []string{\"SPACESHIP_API_KEY\", \"SPACESHIP_API_SECRET\"} {\n\tif os.Getenv(k) == \"\" {\n\t\treturn fmt.Errorf(\"missing %s\", k)\n\t}\n}\nif domain.DomainName == \"\" {\n\treturn errors.New(\"spaceship: domain required\")\n}","typeGuard":"// parse the wrapped Detail for classification\nfunc detailOf(err error) string {\n\ts := errString(err)\n\tif strings.HasPrefix(s, \"request error: \") {\n\t\treturn strings.TrimPrefix(s, \"request error: \")\n\t}\n\treturn \"\"\n}","tryCatchPattern":"if err != nil {\n\tswitch d := detailOf(err); {\n\tcase strings.Contains(d, \"auth\") || strings.Contains(d, \"key\"):\n\t\tlog.Fatal(\"spaceship: check API key/secret\")\n\tcase strings.Contains(d, \"rate\"):\n\t\ttime.Sleep(time.Minute) // back off and retry\n\tdefault:\n\t\treturn err\n\t}\n}","preventionTips":["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"],"tags":["api-error","http-status","spaceship"],"backgroundTag":"http-non-2xx-api-response","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}