{"record":{"id":"0911c388a35e75d3","repo":"Tencent/WeKnora","slug":"mineru-cloud-state-done-but-no-markdown-content-or","errorCode":null,"errorMessage":"MinerU Cloud state=done but no markdown/content or full_zip_url","messagePattern":"MinerU Cloud state=done but no markdown/content or full_zip_url","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/mineru_cloud_converter.go","lineNumber":339,"sourceCode":"\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\")\n\t}\n\n\tmd, imageRefs, err := downloadAndExtractZip(item.FullZipURL)\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"extract zip: %w\", err)\n\t}\n\n\tlogger.Infof(context.Background(), \"[MinerUCloud] parsed (zip), markdown=%d chars, images=%d\", len(md), len(imageRefs))\n\treturn md, imageRefs, nil\n}\n\n// --- ZIP handling ---\n\nvar imgRefPattern = regexp.MustCompile(`!\\[[^\\]]*\\]\\(([^)]+)\\)`)\n\nfunc downloadAndExtractZip(zipURL string) (string, []types.ImageRef, error) {\n\tif err := utils.ValidateURLForSSRF(zipURL); err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"zip URL blocked by SSRF check: %v\", err)","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/mineru_cloud_converter.go#L321-L357","documentation":"The MinerU Cloud batch item reported state=done, but the parsed item contains no inline markdown/content text and no full_zip_url to download results from, so extractDoneResult has nothing to return (mineru_cloud_converter.go:339). This indicates an inconsistent server response: the task claims completion but carries no result payload. The library treats this as fatal for the item.","triggerScenarios":"pollBatchResult -> extractDoneResult receives an item with state \"done\" where both the inline markdown/content fields are empty and item.FullZipURL == \"\" — a done item lacking any result payload.","commonSituations":"MinerU Cloud partially completed the task (processing error internally marked done); API change removing/renaming the markdown/content/full_zip_url fields so they no longer unmarshal; result retention expiry zeroing out payloads while state stays 'done'.","solutions":["Dump the raw extractResultItem JSON to confirm whether full_zip_url/markdown/content were present but not unmarshaled (field-name mismatch).","Update the extractResultItem struct tags to match the current API field names.","Re-submit the document — a done state with no payload usually means the server-side conversion actually failed.","Check result retention: if the batch was created long ago, results may have been purged; poll promptly after completion."],"exampleFix":"// before\nFullZipURL string `json:\"fullZipUrl\"`\n// after — correct the json tag to match the API\nFullZipURL string `json:\"full_zip_url\"`\nMarkdown   string `json:\"markdown\"`","handlingStrategy":"validation","validationCode":"func isUsableDoneItem(item extractResultItem) bool {\n    return item.State == \"done\" &&\n        (item.Markdown != \"\" || item.Content != nil || item.FullZipURL != \"\")\n}","typeGuard":"func hasResultPayload(item extractResultItem) bool {\n    return item.FullZipURL != \"\" || item.Markdown != \"\"\n}","tryCatchPattern":"md, images, err := pollBatchResult(ctx, batchID)\nif err != nil {\n    if strings.Contains(err.Error(), \"state=done but no markdown/content or full_zip_url\") {\n        // server said done but delivered nothing: re-submit\n        return resubmitBatch(ctx, doc)\n    }\n    return err\n}","preventionTips":["Verify extractResultItem json tags match the current API field names so payloads aren't silently dropped.","Treat a done state with no payload as a server-side conversion failure and re-submit.","Poll results soon after completion to avoid retention purge."],"tags":["cloud-service","api-contract","empty-response","go"],"backgroundTag":"empty-api-result-payload","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}