micro/go-micro · error
failed to parse submit response
Error message
failed to parse submit response: %w
What it means
GenerateImage wraps the json.Unmarshal error when decoding the 200 submit response into {code, message, data:{id,status}}. A 200 body that is not this envelope (empty body, HTML, changed field types) triggers it, meaning the API succeeded at HTTP level but the payload is unreadable.
Solutions
- Log string(respBody) alongside the error to compare the actual payload to the expected envelope.
- Check Content-Type of the 200 response for text/html from an intermediary.
- Update the provider struct if AtlasCloud changed its response schema; capture io.ReadAll errors to detect truncation.
- Pin the API version in BaseURL if the provider offers versioned endpoints.
Example fix
if err := json.Unmarshal(respBody, &submitResp); err != nil {
return nil, fmt.Errorf("failed to parse submit response: %w (body: %.200s)", err, string(respBody))
} Defensive patterns
Strategy: try-catch
Type guard
func looksLikeSubmitEnvelope(body []byte) bool {
var probe struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
}
return json.Unmarshal(body, &probe) == nil && probe.Data != nil
} Try / catch
img, err := provider.GenerateImage(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed to parse submit response") {
log.Printf("AtlasCloud submit payload unreadable — dump body and check for schema drift: %v", err)
return err
} Prevention
- Capture and log the raw body on parse failure to diagnose schema changes fast.
- Pin API versions where possible and watch AtlasCloud changelogs.
- Verify intermediaries (WAF/proxy) don't rewrite 200 response bodies.
- Read io.ReadAll's error instead of discarding it to catch truncated bodies.
When it happens
Trigger: json.Unmarshal(respBody, &submitResp) fails after a 200 from the image endpoint: empty/truncated body, HTML from a proxy, or fields whose types changed (e.g. code returned as string).
Common situations: Provider API version drift changing the response envelope; gateway/WAF injecting content into 200 responses; response body truncated by network issues (io.ReadAll error ignored).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/0fee88cd98d31f8d.
Report an issue: GitHub.
Appendix: source
Thrown at ai/atlascloud/atlascloud.go:976
return nil, fmt.Errorf("API request failed: %w", err)
}
defer httpResp.Body.Close()
respBody, _ := io.ReadAll(httpResp.Body)
if httpResp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API error (%s): %s", httpResp.Status, string(respBody))
}
var submitResp struct {
Code int `json:"code"`
Msg string `json:"message"`
Data struct {
ID string `json:"id"`
Status string `json:"status"`
} `json:"data"`
}
if err := json.Unmarshal(respBody, &submitResp); err != nil {
return nil, fmt.Errorf("failed to parse submit response: %w", err)
}
if submitResp.Code != 200 {
return nil, fmt.Errorf("API error: %s", submitResp.Msg)
}
predictionID := submitResp.Data.ID
pollURL := strings.TrimRight(p.opts.BaseURL, "/") + "/api/v1/model/prediction/" + predictionID
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-ticker.C:
result, err := p.pollPrediction(ctx, pollURL)
if err != nil {View on GitHub (pinned to 24529f1404)