{"record":{"id":"bb7b1a9978d3d706","repo":"Tencent/WeKnora","slug":"decode-extract-result-object-w","errorCode":null,"errorMessage":"decode extract_result object: %w","messagePattern":"decode extract_result object: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/mineru_cloud_converter.go","lineNumber":321,"sourceCode":"\t\tlogger.Infof(context.Background(), \"[MinerUCloud] Raw extract_result: %s\", rawExtract)\n\t}\n\n\t// Pretty-print the structure to reveal all available fields\n\tvar rawObj interface{}\n\tif err := json.Unmarshal(pollResp.Data.ExtractResult, &rawObj); err == nil {\n\t\tlogResponseStructure(\"MinerUCloud\", rawObj, \"extract_result\")\n\t}\n\n\t// The extract_result can be either a single object or an array\n\tvar items []extractResultItem\n\tif pollResp.Data.ExtractResult[0] == '[' {\n\t\tif err := json.Unmarshal(pollResp.Data.ExtractResult, &items); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decode extract_result array: %w\", err)\n\t\t}\n\t} else {\n\t\tvar single extractResultItem\n\t\tif err := json.Unmarshal(pollResp.Data.ExtractResult, &single); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"decode extract_result object: %w\", err)\n\t\t}\n\t\titems = []extractResultItem{single}\n\t}\n\n\treturn items, nil\n}\n\n// extractDoneResult extracts markdown and images from a completed batch item.\n// Prefers inline markdown/content fields; falls back to downloading full_zip_url.\nfunc (c *MinerUCloudReader) extractDoneResult(_ context.Context, item *extractResultItem) (string, []types.ImageRef, error) {\n\ttext := firstNonEmpty(item.Markdown, item.Content, item.Text)\n\tif text != \"\" {\n\t\tlogger.Infof(context.Background(), \"[MinerUCloud] parsed (inline), length=%d\", len(text))\n\t\treturn text, nil, nil\n\t}\n\n\tif item.FullZipURL == \"\" {\n\t\treturn \"\", nil, fmt.Errorf(\"MinerU Cloud state=done but no markdown/content or full_zip_url\")","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/mineru_cloud_converter.go#L303-L339","documentation":"The extract_result field did not start with '[', so the library decodes it as a single extractResultItem object; that object decode failed (mineru_cloud_converter.go:321). This means the doubly-encoded JSON inside extract_result is neither a valid single item object nor (per 853) a valid array. Usually the payload is malformed or the schema diverged from extractResultItem.","triggerScenarios":"fetchBatchStatus receives extract_result that is neither '['-prefixed nor a JSON object matching extractResultItem — e.g. a quoted plain string, an object with renamed fields, or corrupted doubly-encoded JSON.","commonSituations":"MinerU Cloud returning a failure/status-only object without the expected fields plus changed types; API upgrades changing field names (e.g. full_zip_url moved); mocking/stub environments returning simplified payloads.","solutions":["Log the raw extract_result string to see the actual shape returned.","Update extractResultItem to match the current MinerU Cloud response schema.","Add a fallback decode into json.RawMessage / map[string]any to introspect unknown shapes instead of failing outright.","Verify you are using a compatible MinerU Cloud API version/endpoint."],"exampleFix":"// before\nvar single extractResultItem\nif err := json.Unmarshal(pollResp.Data.ExtractResult, &single); err != nil {\n    return nil, fmt.Errorf(\"decode extract_result object: %w\", err)\n}\n// after — log the payload for diagnosis\nvar single extractResultItem\nif err := json.Unmarshal(pollResp.Data.ExtractResult, &single); err != nil {\n    return nil, fmt.Errorf(\"decode extract_result object: %w (payload: %.300s)\", err, string(pollResp.Data.ExtractResult))\n}","handlingStrategy":"type-guard","validationCode":"var raw any\nif err := json.Unmarshal(pollResp.Data.ExtractResult, &raw); err != nil {\n    return fmt.Errorf(\"extract_result is not valid JSON: %w\", err)\n}\nif _, ok := raw.(map[string]any); !ok {\n    return errors.New(\"extract_result is not a JSON object\")\n}","typeGuard":"func isExtractResultObject(raw json.RawMessage) bool {\n    var obj map[string]json.RawMessage\n    return json.Unmarshal(raw, &obj) == nil\n}","tryCatchPattern":"items, err := pollBatchResult(ctx, batchID)\nif err != nil {\n    if strings.Contains(err.Error(), \"decode extract_result object\") {\n        // introspect payload; report contract mismatch\n        return fmt.Errorf(\"unexpected extract_result shape: %w\", err)\n    }\n    return err\n}","preventionTips":["Decode into map[string]any first to inspect unknown shapes before binding to a struct.","Watch for MinerU Cloud API field renames (full_zip_url, markdown, state).","Add a regression test that decodes a captured real response."],"tags":["json","decoding","schema","go","api-contract"],"backgroundTag":"json-schema-mismatch","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}