rustup 1.29.3 fixes x86_64 and Solaris regressions
Rustup 1.29.3, announced by the Rustup team on November 3, 2026, is a small but important point release. According to the official announcement and changelog, it fixes two platform-specific regressions that appeared in the 1.29.x line: an "Illegal instruction" error on certain x86_64 CPUs without SSE4.1, and a "lock() not supported" error on Solaris. Neither issue is exotic in the environments where Rust tooling is expected to work reliably. Old x86_64 hardware still shows up in labs, build farms, virtualized test setups, and long-lived infrastructure. Solaris remains a supported target context for projects that care about cross-Unix portability, and the Rust project tracks Solaris-related breakage closely enough that regressions in core tooling get immediate attention.
The value of a patch release like 1.29.3 is not that it introduces new workflow features. Its value is operational: it restores the assumption that the toolchain manager itself will behave predictably across the platforms it claims to serve. Rustup sits at the boundary between developer workflows, CI runners, package downloads, filesystem state, and platform-specific system behavior. When rustup crashes or cannot write its own state files, the failure is upstream of almost every other Rust task. That makes narrow, well-scoped fixes especially important. In this case, the Rustup team shipped targeted corrections, documented manual recovery steps for environments where self-update had already failed, and linked the fixes to the public pull requests and changelog entries.
This release also arrived shortly after rustup 1.29.2, which the Rustup team announced on October 20, 2026. Rustup 1.29.2 was focused on dependency updates: it updated rustls-webpki and webpki-root-certs to address the eMudhra intermediate certificates issue described in CVE-2026-111943, with RUSTSEC-2026-0382 referenced from the announcement and changelog. Reading 1.29.2 and 1.29.3 together is useful because it shows the normal shape of maintenance work in this part of the ecosystem. Security-sensitive dependency hygiene and platform regressions can land close together, but they are different problems with different verification paths. A responsible upgrade plan should account for both.
What rustup 1.29.3 changed
The official rustup 1.29.3 announcement lists two fixes:
- Fixed "Illegal instruction" error on certain x86_64 CPUs without SSE4.1. The announcement links rustup pull request #5162.
- Fixed "
lock()not supported" error on Solaris. The announcement links rustup pull request #5167.
The stable changelog entry for 1.29.3 repeats the same two items. The announcement also includes standard update instructions: stop programs that may be using rustup and run rustup self update, or allow rustup to update itself at the end of a normal rustup update. For this release, the team added a manual recovery path for users who hit self-update problems: download the corresponding rustup-init binary, make sure no other rustup processes are running, and replace the existing rustup binary with the downloaded rustup-init renamed to rustup. The post notes that the binary is often located at $HOME/.cargo/bin/rustup, or $CARGO_HOME/bin/rustup when CARGO_HOME is overridden.
Those operational details matter because the two regressions fixed in 1.29.3 can prevent normal rustup commands from completing. If the binary crashes with an illegal instruction, a routine rustup check or update flow may not be a reliable recovery mechanism on the affected machine. If filesystem locking fails on Solaris while rustup is trying to write settings or other state, the installation can fail before a self-managed update path becomes useful. The manual replacement procedure is therefore part of the fix story, not an afterthought.
The x86_64 regression: illegal instructions without SSE4.1
The x86_64 issue is tracked publicly as rust-lang/rustup#5160, titled "Illegal instruction on stable-x86_64-unknown-linux-gnu". The issue reporter described the failure after upgrading rustup from 1.29.1 to 1.29.2 on Debian 13 Trixie running on an Athlon II X4 64 system (Linux 6.12.113+deb13-amd64 x86_64 GNU/Linux). The observed symptom was simple and severe: running rustup check produced an "Illegal instruction" error.
The issue discussion provides important diagnostic context. A commenter identified the problem as related to RustCrypto/stream-ciphers#579 and reported reproducing it on a CPU with SSE2 but without SSE4.1. The backtrace in that comment showed execution reaching core::core_arch::x86::sse41::_mm_extract_epi32 inside the chacha20 crate path, specifically through <chacha20::ChaChaCore<chacha20::R12, chacha20::variants::Legacy> as rand_core::block::Generator>::generate and into rustup::utils::raw::random_string. The stack continued through rustup download and installation paths, including temporary-file creation and manifest download logic.
That trace is useful because it narrows the failure from "rustup is broken on old CPUs" to a concrete execution path: a code path using chacha20 executed an SSE4.1 intrinsic on hardware that did not support that instruction set. The issue comment also reported that updating chacha20 from v0.10.1 (noted as yanked) to v0.10.2 fixed the issue.
How pull request #5162 addressed the problem
rustup pull request #5162, "Update chacha20 in release", was authored by Chris Denton and merged by djc into the release/1.29 branch on October 24, 2026. The pull request states that it fixes issue #5160 and notes that another point release would be needed. The actual code change in the PR is narrow: it updates the chacha20 dependency in Cargo.lock from version 0.10.1 to 0.10.2.
This detail is worth stating carefully. The public rustup PR does not show rustup implementing its own SSE4.1 detection or fallback routine. Instead, rustup consumed an updated chacha20 crate release that resolved the illegal-instruction behavior in the affected path. That distinction matters for accuracy. A good post should not invent internal rustup logic that is not present in the verified change. At the same time, it can explain why a dependency bump in a cryptographic/randomness-related crate can have a platform-specific crash impact: rustup uses dependencies in runtime paths, and an unsafe or architecture-specific implementation choice in a dependency can surface as a fatal CPU instruction fault in the host tool.
The issue and PR also illustrate why patch releases sometimes favor minimal dependency movement. In the PR discussion, djc asked whether all semver-compatible dependencies should be updated, and Chris Denton responded that for a patch release it could be riskier to update so much at once. That tradeoff is visible directly in the public record: the fix was scoped to the dependency implicated by the regression, and the team prepared a point release rather than broadening the change set.
Practical implications for x86_64 environments
For operators and developers, the main lesson from the SSE4.1 regression is to treat CPU feature compatibility as part of the toolchain environment, especially on older hardware or constrained virtual machines. The issue was not reported as a generic x86_64 failure; it affected certain x86_64 CPUs without SSE4.1. The reporter's Athlon II X4 64 example is a useful reminder that "x86_64" describes an architecture family, not a uniform set of later instruction extensions.
When diagnosing similar failures, the first step is to capture exact symptoms and environment details: rustup version, host target, operating system, kernel, CPU model, and the command that triggered the crash. Tools such as uname -a, rustup --version, and CPU feature inspection utilities can help establish whether the machine lacks SSE4.1. The second step is to check the release notes and changelog for the installed rustup version. In this case, rustup 1.29.3 explicitly names the affected condition.
If the affected machine cannot self-update cleanly, the Rustup 1.29.3 announcement's manual recovery steps are the verified path: stop other rustup processes, download the appropriate rustup-init, and replace the existing rustup binary. That procedure is especially relevant for CI runners and build agents where an automated update loop may repeatedly hit the crashing binary before package caches or base images are refreshed.
The Solaris regression: lock() not supported
The Solaris issue is tracked as rust-lang/rustup#5164, "Solaris support is broken on 1.29.2". The report came from JohnTitor and included a concrete failure from CI: downloading the installer with curl against https://sh.rustup.rs/ led to the error could not write settings file: '/root/.rustup/settings.toml': lock() not supported. The issue notes that it was observed in a Solaris 11.4-gcc context and that the problem would affect toolchains broadly because it occurs in rustup's settings-writing path.
The issue identifies a cause: rust-lang/rust#157509 removed lock(). It also points to prior art in Cargo, specifically rust-lang/cargo#17110, as a possible direction for an alternative implementation. This is a classic portability failure mode. Rustup needs to protect shared or sequentially updated state on disk; if the platform or standard library behavior around file locking changes, code that assumed the previous interface or behavior can fail at runtime even when the higher-level logic is unchanged.
The symptom reported in #5164 is especially disruptive because it occurs while rustup is trying to write its own settings file. That means the failure can appear very early in installation or setup flows, not just during advanced operations. For package maintainers, CI maintainers, and users of Solaris environments, the effect is not a subtle edge case; it blocks rustup from establishing or updating local state.
How pull request #5167 fixed Solaris locking
rustup pull request #5167, "Support file locking on Solaris", was authored by Chris Denton and merged by rami3l into rustup's main branch on October 29, 2026. The PR description says it fixes issue #5164, is mostly a copy/paste from Cargo's implementation, and adds a Clippy restriction lint to prevent accidentally using File::lock directly.
The patch provides verifiable implementation details. It adds clippy.toml entries that disallow std::fs::File::lock, lock_shared, try_lock, and related direct usage patterns where appropriate, pointing developers to crate::utils::raw::lock or crate::utils::raw::lock_shared and noting Solaris support constraints. It updates src/cli/self_update/stage.rs to use utils::raw::lock and utils::raw::try_lock. It updates src/utils/raw.rs so locked reads and writes use lock_shared/lock helpers rather than direct File methods.
The most important part for Solaris is the new flock module in src/utils/raw.rs. On non-Solaris platforms, it is a thin wrapper around the standard File locking methods. On Solaris, it implements locking with fcntl, using F_WRLCK and F_RDLCK with F_SETLKW for blocking locks and F_SETLK for try-lock behavior. The code constructs a libc::flock covering the whole file, retries interrupted blocking lock attempts, and treats EACCES, EAGAIN, or WouldBlock as a would-block condition for try-lock. The code comment states that it is adapted from Cargo and references the related Rust issue context for Solaris file-locking support.
This is the kind of fix that cross-platform infrastructure projects need: a platform-specific implementation behind a small internal abstraction, plus guardrails to keep future code from reintroducing the unsupported call. The Clippy disallowed-methods configuration is especially useful because it turns a portability lesson into an enforceable rule.
Update and recovery guidance
The Rustup team recommends the normal update path where possible: rustup self update, or rustup update as part of regular toolchain maintenance. If 1.29.2 or a partially broken environment prevents self-update, follow the manual replacement steps from the 1.29.3 announcement. On systems where rustup is managed by a distribution, CI image, container base layer, or internal mirror, updating the packaged rustup binary or image may be more reliable than relying on an in-place self-update from a broken state.
Before and after updating, it helps to record a small amount of evidence. Check rustup --version, the host triple, and whether the previously failing command now succeeds. For the SSE4.1 case, that might be rustup check or another command that previously crashed. For Solaris, it might be the installation/bootstrap flow or any operation that previously failed while writing settings. Avoid treating a successful download alone as proof of recovery; the relevant proof is that rustup can execute and manage its state on the affected platform.
The announcement also includes a general caveat: anti-malware scanners can interfere with rustup after a new release, especially around operations that create or copy many small files such as installing rust-docs. That caveat is separate from the regressions fixed in 1.29.3, but it is worth keeping in mind when diagnosing post-update failures.
Why these fixes matter beyond one point release
Rustup 1.29.3 is a reminder that "tooling stability" includes more than high-level command UX. It includes dependency behavior on specific CPU features, standard-library or OS interface changes, filesystem locking semantics, and the ability to recover when the updater itself is affected. The x86_64 fix shows how a small dependency update can resolve a severe crash caused by an instruction not available on older hardware. The Solaris fix shows how an internal abstraction and platform-specific fcntl implementation can restore basic state management when a previous locking approach is unavailable.
For users, the action is straightforward: upgrade to rustup 1.29.3 or newer, use the manual binary replacement path if self-update is broken, and keep the primary release notes, changelog, and linked pull requests in view when evaluating platform-specific incidents. For maintainers of CI environments, the broader lesson is to include toolchain-manager health checks in base image validation, especially on less common platforms or older CPU fleets. A broken compiler is obvious; a broken updater or settings writer can quietly block every downstream Rust workflow.
Sources
- Announcing rustup 1.29.3
- rustup CHANGELOG.md (1.29.3)
- Pull request #5162: Update chacha20 in release
- Issue #5160: Illegal instruction on stable-x86_64-unknown-linux-gnu
- Pull request #5167: Support file locking on Solaris
- Issue #5164: Solaris support is broken on 1.29.2
- Announcing rustup 1.29.2