orjson 3.10.15 was the only package that failed to build on Windows ARM64
In this article
Installing orjson 3.10.15 failed after taking 113.28 seconds.
This was a small check: create a new venv and install httpx, rich, pydantic, and orjson one at a time. The first three passed, and only the last produced an error. If I had installed them together, it would have been harder to see where the wait occurred. The way it failed was unexpected.
I had been thinking too loosely that if a Python package failed on Windows ARM64, packages with native extensions would all get stuck together. What caught me off guard was pydantic succeeding normally. pydantic_core includes a Rust native extension, but its wheel tag was cp312-cp312-win_arm64. Even for Rust extensions, the result depends on whether an ARM64 Windows wheel is published. Looking only at whether it is written in Rust does not predict whether installation will work.
The measurement date was 2026-07-11. I created the venv with ARM64 Python 3.12.10 and installed with pip 25.0.1, adding --no-cache-dir. Creating the venv itself took 19.33 seconds.
Installing one package at a time
The procedure was simple: create a new venv, then install four packages one by one. I did not run one combined pip install because I wanted to separate which package consumed time and when the failure occurred. A batch install blurs the source of the wait.
C:\Users\akirasakai\AppData\Local\Programs\Python\Python312-arm64\python.exe -m venv C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv
C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv\Scripts\python.exe -m pip install --no-cache-dir -q httpx==0.28.1
C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv\Scripts\python.exe -m pip install --no-cache-dir -q rich==13.9.4
C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv\Scripts\python.exe -m pip install --no-cache-dir -q pydantic==2.10.6
C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv\Scripts\python.exe -m pip install --no-cache-dir -q orjson==3.10.15
Because --no-cache-dir was present, there was less opportunity to take an easy path using a wheel left locally. A pure-Python wheel installs straightforwardly even under this condition, so the issue is packages that need a platform-specific binary. In this run, that was orjson.
The venv creation also emitted a junction-related warning. It was not an error; the return code was 0. It was not the main issue here, but the short AKIRAS~1 path and the normal akirasakai path are mixed, which can be confusing when reading the log. While looking for a failure cause, it is easy to be distracted by output like this.
Wait times and return codes
This was not a repeated measurement; it is a one-run field log. I am not giving a median, and I am leaving each command's return code and elapsed time as-is. The table is meant to preserve the order of the failure, not reproducibility.
| Target | Elapsed time | rc | Result |
|---|---|---|---|
| Create venv | 19.33 seconds | 0 | Worked |
| httpx==0.28.1 | 16.14 seconds | 0 | Worked |
| rich==13.9.4 | 28.74 seconds | 0 | Worked |
| pydantic==2.10.6 | 17.05 seconds | 0 | Worked |
| orjson==3.10.15 | 113.28 seconds | 1 | Failed |
Waiting 113.28 seconds and then getting a failure feels very long. It did not immediately say “the compatible wheel is missing”; it proceeded into a build and then failed. During the wait, the screen looked as though work was progressing, which made it more confusing. I thought I was only adding one dependency for lightweight log processing, but the environment setup suddenly acquired a separate build problem. The error also appears only after going deep into the Rust side, so it takes time to decide whether to choose another package or repair the environment. A dependency added for light JSON output brings in the Rust toolchain, maturin, cargo, and the local build environment all at once, so the scope to inspect after the failure becomes too large.
After installation, pip list --format=json still contained httpx 0.28.1, rich 13.9.4, pydantic 2.10.6, and pydantic_core 2.27.2. There was no orjson entry, and it was helpful that the failed package did not remain half-installed.
Seeing the difference in wheel tags
The key point is that the successful packages did not all succeed for the same reason. httpx and rich, along with their dependencies, use py3-none-any pure-Python wheels, so they largely do not care whether the platform is ARM64 or x64. Pydantic itself is py3-none-any, but the component it actually uses, pydantic_core, had cp312-cp312-win_arm64.
| Package | Wheel tag | Interpretation |
|---|---|---|
| httpx | py3-none-any | Pure Python |
| httpcore | py3-none-any | Pure Python |
| anyio | py3-none-any | Pure Python |
| certifi | py3-none-any | Pure Python |
| h11 | py3-none-any | Pure Python |
| idna | py3-none-any | Pure Python |
| rich | py3-none-any | Pure Python |
| markdown_it_py | py3-none-any | Pure Python |
| mdurl | py3-none-any | Pure Python |
| pygments | py3-none-any | Pure Python |
| pydantic | py3-none-any | Pure-Python side of the package |
| pydantic_core | cp312-cp312-win_arm64 | Native extension for Windows ARM64 |
| annotated_types | py3-none-any | Pure Python |
| typing_extensions | py3-none-any | Pure Python |
| pip | py3-none-any | Pure Python |
As observed here on July 11, 2026, only orjson 3.10.15 lacked a win_arm64 wheel. The table makes it fairly clear why pydantic installed. It is not that Rust packages fail. A Rust extension with an ARM64 Windows wheel installs; without one, it proceeds to a source build. That creates a dependency on the local toolchain.
The existing pip-arm64-wheels work compares wheel availability across 20 packages. This was not that inventory; it is a field record of one package waiting 113.28 seconds and then failing. A list alone does not convey how unpleasant that wait is.
Where it failed
pip could not find a prebuilt wheel for orjson on win_arm64 and tried to build it from source. Since orjson is written in Rust, the build involves maturin and cargo. I had not installed the Rust toolchain in my environment. The error therefore appeared after entering the Rust-side build.
The end of the log looked like this.
ror
warning: build failed, waiting for other jobs to finish...
error: could not compile `proc-macro2` (build script) due to 1 previous error
error: could not compile `serde` (build script) due to 1 previous error
error: could not compile `rustversion` (build script) due to 1 previous error
error: could not compile `libc` (build script) due to 1 previous error
error: could not compile `target-lexicon` (build script) due to 1 previous error
maturin failed
Caused by: Failed to build a native library through cargo
Caused by: Cargo build finished with "exit code: 101": `"cargo" "rustc" "--profile" "release" "--message-format" "json-render-diagnostics" "--manifest-path" "C:\\Users\\akirasakai\\AppData\\Local\\Temp\\pip-install-8n8qgl88\\orjson_e12791a1a3a54fafbaca1e8d479de68a\\Cargo.toml" "--lib"`
Error: command ['maturin', 'pep517', 'build-wheel', '-i', 'C:\\Users\\AKIRAS~1\\AppData\\Local\\Temp\\arm64lab_c\\venv\\Scripts\\python.exe', '--compatibility', 'off'] returned non-zero exit status 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for orjson
[notice] A new release of pip is available: 25.0.1 -> 26.2
[notice] To update, run: C:\Users\AKIRAS~1\AppData\Local\Temp\arm64lab_c\venv\Scripts\python.exe -m pip install --upgrade pip
ERROR: Failed to build installable wheels for some pyproject.toml based projects (orjson)
could not compile libc (build script), maturin failed, and Cargo build finished with "exit code: 101" appear together at the end. The useful reading is not that pip itself broke, but that the missing wheel sent installation down the build path and the Rust side then failed.
How I would choose packages
For this run, I want to stop at the conclusion that orjson 3.10.15 does not work in this Windows ARM64 environment. Installing Rust might make a build possible, but I currently have little reason to go that far. What I actually needed was lightweight log processing and configuration-file reads and writes. Waiting 113.28 seconds to fail is not worth it for that use.
First, consider whether the standard json module is sufficient. There are cases where orjson is desirable for speed, but this local use case was not worth accepting the failure. If removing one dependency is possible, operations are easier.
I would keep pydantic. pydantic_core has cp312-cp312-win_arm64, so it was installable under these conditions. Treating “Rust-based means it all fails” as a rule would lead to the wrong decision.
In short, pure-Python wheels are in the safe zone, and native extensions with an ARM64 wheel are usable. A package like orjson 3.10.15 without a win_arm64 wheel becomes a different task as soon as it enters a source build. Personally, when creating everyday venvs on Windows ARM64, I now look first for places where the standard library is enough.
The next measurement would be to install the Rust toolchain and see how much of the same failure changes. That belongs in another article. This one remains a failure record: in a new venv with nothing added, only orjson failed. The question of why it waited this long remains open.