{"record":{"id":"14f8980b898fed99","repo":"chenhg5/cc-connect","slug":"s-resource-download-requires-non-empty-messageid","errorCode":null,"errorMessage":"%s: resource download requires non-empty messageID and fileKey","messagePattern":"(.+?): resource download requires non-empty messageID and fileKey","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":77,"sourceCode":"// Behaviour:\n//   - Always issues a single Range bytes=0-0 GET first. If the server honours\n//     Range (206) we then loop the remaining chunks; if it doesn't (200) we\n//     already have the full body — done.\n//   - On any transient network error mid-loop: retries with exponential\n//     backoff up to maxTransientRetries before giving up.\n//\n// One GET is the minimum regardless of file size: small files return 200 and\n// we are done; large files return 206 with the first chunk, then we loop.\n// This avoids the wasted HEAD round-trip and keeps the \"small file\" path\n// observable as exactly one outbound request, matching pre-#1741 behaviour\n// for files under Feishu's streaming cap.\n//\n// messageID and fileKey come from the inbound message envelope; resType is\n// the Feishu resource-type segment (\"file\", \"image\", ...). The caller MUST\n// guarantee these have already been validated (no empty strings).\nfunc (p *Platform) downloadResourceChunked(ctx context.Context, messageID, fileKey, resType string) ([]byte, error) {\n\tif strings.TrimSpace(messageID) == \"\" || strings.TrimSpace(fileKey) == \"\" {\n\t\treturn nil, fmt.Errorf(\"%s: resource download requires non-empty messageID and fileKey\", p.tag())\n\t}\n\tif p.resourceDownloadHTTP == nil {\n\t\t// Defensive: callers running outside the normal constructor (notably\n\t\t// unit tests that synthesise a Platform value) still get a sane\n\t\t// client. We log instead of panicking so one stale test fixture\n\t\t// doesn't crash the whole process.\n\t\tslog.Warn(p.tag() + \": resourceDownloadHTTP is nil; using default client\")\n\t\tp.resourceDownloadHTTP = &http.Client{Timeout: 60 * time.Second}\n\t}\n\tif p.resourceChunkSize <= 0 {\n\t\tp.resourceChunkSize = defaultResourceChunkSize()\n\t}\n\tif p.resourceMaxBytes <= 0 {\n\t\tp.resourceMaxBytes = defaultResourceMaxBytes\n\t}\n\n\ttoken, err := p.fetchResourceTokenOrDefault(ctx)\n\tif err != nil {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L59-L95","documentation":"downloadResourceChunked refuses to run when messageID or fileKey is empty/whitespace. These values come from the inbound message envelope and are required to build the Feishu resource-download URL; the guard exists because the function itself documents that callers must pre-validate them.","triggerScenarios":"downloadImage/downloadResource called with an empty or whitespace-only messageID or fileKey — e.g. an inbound message missing an image key, or a caller passing zero-value strings.","commonSituations":"Upstream message parsing produced empty file_key (unsupported message type); caller forgot to trim/validate envelope fields; tests synthesizing Platform values with blank identifiers.","solutions":["Validate messageID and fileKey are non-empty at the call site before invoking downloadResource/downloadImage","Inspect the inbound message envelope — the field was likely absent in the original message","Trim whitespace and reject earlier in the message-parsing layer with a clearer error","If the message legitimately lacks a fileKey, handle that message type separately instead of attempting a resource download"],"exampleFix":"// before\np.downloadResource(ctx, msgID, fileKey, \"image\")\n// after\nif strings.TrimSpace(msgID) == \"\" || strings.TrimSpace(fileKey) == \"\" {\n    return nil, fmt.Errorf(\"feishu: cannot download resource: empty messageID or fileKey\")\n}\np.downloadResource(ctx, msgID, fileKey, \"image\")","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(messageID) == \"\" || strings.TrimSpace(fileKey) == \"\" {\n    return fmt.Errorf(\"feishu: resource download needs non-empty messageID and fileKey\")\n}","typeGuard":null,"tryCatchPattern":"data, err := p.DownloadImage(ctx, msgID, fileKey)\nif err != nil {\n    if strings.Contains(err.Error(), \"non-empty messageID\") {\n        // skip download; message lacked a usable key\n    }\n}","preventionTips":["Validate envelope fields immediately after message parsing","Trim identifiers before use","Handle unsupported message types before attempting downloads"],"tags":["feishu","validation","download","required-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}