{"record":{"id":"be406d3a38844ab7","repo":"larksuite/cli","slug":"draft-raw-eml-is-empty","errorCode":null,"errorMessage":"draft raw EML is empty","messagePattern":"draft raw EML is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/parse.go","lineNumber":49,"sourceCode":"\tsnapshot := &DraftSnapshot{\n\t\tDraftID: raw.DraftID,\n\t\tHeaders: headers,\n\t\tBody:    root,\n\t}\n\tif err := refreshSnapshot(snapshot); err != nil {\n\t\treturn nil, err\n\t}\n\treturn snapshot, nil\n}\n\n// maxRawEMLSize is the maximum accepted raw (base64-encoded) EML string length.\n// Base64 encodes 3 bytes into 4 chars, so 35 MB covers a 25 MB decoded EML with margin.\nconst maxRawEMLSize = 35 * 1024 * 1024\n\nfunc decodeRawEML(raw string) ([]byte, error) {\n\traw = strings.TrimSpace(raw)\n\tif raw == \"\" {\n\t\treturn nil, fmt.Errorf(\"draft raw EML is empty\")\n\t}\n\tif len(raw) > maxRawEMLSize {\n\t\treturn nil, fmt.Errorf(\"draft raw EML is too large (%d bytes, max %d)\", len(raw), maxRawEMLSize)\n\t}\n\tdecoders := []func(string) ([]byte, error){\n\t\tbase64.URLEncoding.DecodeString,\n\t\tbase64.RawURLEncoding.DecodeString,\n\t\tbase64.StdEncoding.DecodeString,\n\t\tbase64.RawStdEncoding.DecodeString,\n\t}\n\tfor _, decode := range decoders {\n\t\tdecoded, err := decode(raw)\n\t\tif err == nil {\n\t\t\treturn normalizeLineEndings(decoded), nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"draft raw EML is not valid base64url\")\n}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/parse.go#L31-L67","documentation":"decodeRawEML validates the base64url-encoded EML string passed to Parse before decoding. This error means the caller supplied an empty (or whitespace-only) raw string, so there is nothing to decode into a draft EML document. The parser refuses early instead of producing a confusing downstream parse failure.","triggerScenarios":"Calling Parse with raw == \"\" or a string containing only whitespace (TrimSpace empties it); typically the draft's raw EML field was never fetched or a variable was left zero-valued.","commonSituations":"Fetching a draft whose body is empty/unsaved, forgetting to populate the raw EML field from a Lark mail API response before parsing, wiring the wrong struct field, or reading an empty file/env var into the raw string.","solutions":["Populate the raw string with the base64url-encoded EML from the mail API response before calling Parse","Check the field you are passing is the raw EML (e.g. body.Raw or similar), not an unrelated empty string field","Guard the call site: skip Parse or return a clearer error when the source draft has no raw content"],"exampleFix":"// before\npart, err := draft.Parse(draft.Raw)\n// after\nif draft.Raw == \"\" {\n    return fmt.Errorf(\"draft %s has no raw EML to parse\", draft.ID)\n}\npart, err := draft.Parse(draft.Raw)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(rawEML) == \"\" {\n    return errors.New(\"no raw EML content: fetch the draft body before parsing\")\n}","typeGuard":null,"tryCatchPattern":"part, err := draft.Parse(rawEML)\nif err != nil && strings.Contains(err.Error(), \"draft raw EML is empty\") {\n    // recover by re-fetching the draft raw content, then retry once\n}","preventionTips":["Fetch raw EML content in the same code path that calls Parse","Never pass optional/zero-valued string fields directly into Parse","Trim inputs at the boundary so intent (empty vs whitespace) is explicit"],"tags":["mail","draft","input-validation","empty-input"],"backgroundTag":"missing-required-input","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}