diff --git a/src/openlayer/lib/data/_upload.py b/src/openlayer/lib/data/_upload.py index fd0d30e9..c08f2a3f 100644 --- a/src/openlayer/lib/data/_upload.py +++ b/src/openlayer/lib/data/_upload.py @@ -115,6 +115,8 @@ def upload_bytes_multipart( if isinstance(data, bytes): data = io.BytesIO(data) + # fields can be None when using local storage (presigned URL has no S3 policy fields) + fields = fields or {} upload_fields = {"file": (object_name, data, content_type), **fields} encoder = MultipartEncoder(fields=upload_fields) diff --git a/src/openlayer/lib/tracing/attachment_uploader.py b/src/openlayer/lib/tracing/attachment_uploader.py index f7490f29..bb50448c 100644 --- a/src/openlayer/lib/tracing/attachment_uploader.py +++ b/src/openlayer/lib/tracing/attachment_uploader.py @@ -130,18 +130,24 @@ def upload_attachment(self, attachment: "Attachment") -> "Attachment": if file_bytes is None: raise ValueError(f"No data available for attachment {attachment.name}") - # Upload using the shared upload function + # Upload using the shared upload function. + # presigned_response.fields is None for local storage (only S3 needs policy fields) + try: + fields = ( + dict(presigned_response.fields) + if presigned_response.fields is not None + else {} + ) + except (TypeError, ValueError): + fields = {} + upload_bytes( storage=self._storage, url=presigned_response.url, data=file_bytes, object_name=object_name, content_type=attachment.media_type, - fields=( - dict(presigned_response.fields) - if presigned_response.fields - else None - ), + fields=fields, ) # Set the storage URI on the attachment