Skills single-file ZIP uploads are dropped during file extraction
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 31.6k
- Forks
- 5.7k
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 96
Description
Confirm this is an issue with the Python library and not an underlying OpenAI API
- This is an issue with the Python library.
Describe the bug
client.skills.create(files=("skill.zip", zip_bytes)) silently loses the file and constructs an application/json request with an empty body object. Wrapping the same file tuple in a list correctly produces multipart data.
The Skills create contract accepts either multiple files or a single zip. The SDK tries extraction paths [["files", "<array>"], ["files"]; the array path pops files before noticing that a single file is not a list. The fallback then cannot find it. The async client behaves the same way.
To Reproduce
Run the following against the current Python SDK checkout. It generates a zip in memory and uses MockTransport to inspect the actual public-client request; no API key or live service request is needed.
Code snippets
import io
import zipfile
import httpx2
from openai import OpenAI
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, "w") as archive:
archive.writestr("SKILL.md", "---\nname: example\ndescription: Test skill\n---\n# Example\n")
zip_bytes = buffer.getvalue()
def inspect_request(request):
print(request.headers["content-type"], zip_bytes in request.content)
return httpx2.Response(200, json={}) # Local response fixture only.
with OpenAI(
api_key="fake-key",
base_url="https://example.test",
http_client=httpx2.Client(transport=httpx2.MockTransport(inspect_request)),
) as client:
single = ("skill.zip", zip_bytes)
client.skills.with_raw_response.create(files=single)
client.skills.with_raw_response.create(files=[single])
Actual: the first request reports application/json False; the second reports multipart/form-data; boundary=... True.
Expected: both requests include the zip in multipart data. The single-file field is files, while the list form uses files[].
OS
macOS 26.6.2 ARM64.
Python version
Python 3.13.15.
Library version
Current main source reporting openai 3.14.1, loaded via PYTHONPATH=src; httpx2 2.12.0, Pydantic 2.13.5.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the public client entry point, client.skills.with_raw_response.create, and reproduce the behavior with httpx2.MockTransport using both the single tuple and list forms. Trace the extraction paths for ["files", ""] and ["files"] in the request-building code, including the async client. Done means both forms preserve the ZIP in multipart data, with tests covering the single-file and list cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100