Tencent/WeKnora · error

decode response: %w

Error message

decode response: %w

What it means

parseMinerUFileParseResponse unmarshals the MinerU /file_parse response body into an envelope with a results map. This error means the body is not valid JSON matching that shape — either it isn't JSON at all, or the structure differs (e.g. no top-level 'results' object).

Source

Thrown at internal/infrastructure/docparser/mineru_converter.go:168

		return ""
	}
	return stem
}

func minerUResultLookupKeys(uploadFileName string) []string {
	keys := make([]string, 0, 3)
	if stem := minerUResultStem(uploadFileName); stem != "" {
		keys = append(keys, stem)
	}
	return append(keys, "document", "files")
}

func parseMinerUFileParseResponse(respBody []byte, uploadFileName string) (string, map[string]string, string, error) {
	var envelope struct {
		Results map[string]mineruFileEntry `json:"results"`
	}
	if err := json.Unmarshal(respBody, &envelope); err != nil {
		return "", nil, "", fmt.Errorf("decode response: %w", err)
	}
	if len(envelope.Results) == 0 {
		return "", nil, "", nil
	}

	for _, key := range minerUResultLookupKeys(uploadFileName) {
		if entry, ok := envelope.Results[key]; ok {
			if entry.MDContent != "" || len(entry.Images) > 0 {
				return entry.MDContent, entry.Images, key, nil
			}
		}
	}

	for key, entry := range envelope.Results {
		if entry.MDContent != "" || len(entry.Images) > 0 {
			return entry.MDContent, entry.Images, key, nil
		}
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log a truncated respBody with the error to see the actual payload received.
  2. Verify c.endpoint points at the MinerU API base (…/file_parse), not a UI or proxy route.
  3. Check the MinerU version's API docs and update the envelope struct to match the current schema.
  4. Since a missing 'results' key unmarshals as empty (no error), also confirm status 200 is checked before decoding.

Example fix

// before
var envelope struct {
    Results map[string]mineruFileEntry `json:"results"`
}
if err := json.Unmarshal(respBody, &envelope); err != nil {
    return "", nil, "", fmt.Errorf("decode response: %w", err)
}
// after
var envelope struct {
    Results map[string]mineruFileEntry `json:"results"`
}
if err := json.Unmarshal(respBody, &envelope); err != nil {
    return "", nil, "", fmt.Errorf("decode response (%d bytes, head=%q): %w", len(respBody), respBody[:min(200, len(respBody))], err)
}
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(respBody) {
    return fmt.Errorf("mineru returned non-JSON body (%d bytes)", len(respBody))
}

Type guard

func hasMinerUResults(body []byte) bool {
    var probe struct {
        Results map[string]json.RawMessage `json:"results"`
    }
    return json.Unmarshal(body, &probe) == nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "decode response") {
    // log payload head; treat as contract mismatch, do not retry
    log.Printf("mineru response not parseable: %v", err)
}

Prevention

When it happens

Trigger: json.Unmarshal(respBody, &envelope) fails: server returned HTML error page with 200, plain-text message, or a JSON layout from a different MinerU version (results key missing/renamed, array instead of object).

Common situations: Proxy/gateway error page returned with HTTP 200; MinerU API version upgrade changed the response schema; wrong endpoint path hitting a UI route that returns HTML.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/7640d714e3cc5cc5. Report an issue: GitHub.