{"record":{"id":"f75cc88914ddcb79","repo":"wavetermdev/waveterm","slug":"pdf-file-part-missing-data-f75cc8","errorCode":null,"errorMessage":"PDF file part missing data","messagePattern":"PDF file part missing data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/openai/openai-convertmessage.go","lineNumber":353,"sourceCode":"\t\timageUrl, err := aiutil.ExtractImageUrl(part.Data, part.URL, part.MimeType)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn &OpenAIMessageContent{\n\t\t\tType:       \"input_image\",\n\t\t\tImageUrl:   imageUrl,\n\t\t\tFilename:   part.FileName,\n\t\t\tPreviewUrl: part.PreviewUrl,\n\t\t}, nil\n\n\tcase part.MimeType == \"application/pdf\":\n\t\t// Handle PDFs - OpenAI only supports base64 data for PDFs, not URLs\n\t\tif len(part.Data) == 0 {\n\t\t\tif part.URL != \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"dropping PDF with URL (must be fetched and converted to base64 data)\")\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"PDF file part missing data\")\n\t\t}\n\n\t\t// Convert raw data to base64\n\t\tbase64Data := base64.StdEncoding.EncodeToString(part.Data)\n\n\t\treturn &OpenAIMessageContent{\n\t\t\tType:       \"input_file\",\n\t\t\tFilename:   part.FileName, // Optional filename\n\t\t\tFileData:   base64Data,\n\t\t\tPreviewUrl: part.PreviewUrl,\n\t\t}, nil\n\n\tcase part.MimeType == \"text/plain\":\n\t\ttextData, err := aiutil.ExtractTextData(part.Data, part.URL)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tformattedText := aiutil.FormatAttachedTextFile(part.FileName, textData)","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/openai/openai-convertmessage.go#L335-L371","documentation":"A PDF file part has neither Data nor URL — it's completely empty. The converter requires base64-encodable raw bytes for PDFs, so it rejects the part. This means the attachment failed to load or was never populated upstream.","triggerScenarios":"Constructing an AIMessagePart with MimeType \"application/pdf\" but forgetting to load file bytes into Data; a prior download/read step failed silently leaving Data nil; serializing/deserializing messages lost the binary payload.","commonSituations":"File read errors swallowed upstream; database/blob-store lookups returning empty for the attachment; passing only FileName metadata without content.","solutions":["Populate part.Data with the PDF bytes read from disk/storage before sending","Add an os.ReadFile / storage-fetch error check so empty reads are caught before building the message","Validate that len(part.Data) > 0 for every PDF part in a pre-send validation pass"],"exampleFix":"// before\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"application/pdf\", FileName: path} // no data\n// after\ndata, err := os.ReadFile(path)\nif err != nil { return err }\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"application/pdf\", FileName: path, Data: data}","handlingStrategy":"validation","validationCode":"func ensurePDFData(p uctypes.AIMessagePart) error {\n    if p.MimeType == \"application/pdf\" && len(p.Data) == 0 {\n        return errors.New(\"PDF part has no data\")\n    }\n    return nil\n}","typeGuard":"func hasPDFData(p uctypes.AIMessagePart) bool {\n    return p.MimeType == \"application/pdf\" && len(p.Data) > 0\n}","tryCatchPattern":null,"preventionTips":["Check os.ReadFile / storage errors instead of ignoring them","Assert attachment bytes are non-empty right after load","Validate parts before building the chat request"],"tags":["openai","pdf","message-conversion","missing-data"],"backgroundTag":"attachment-data-missing","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}