bazelbuild / bazelbuild/rules_rust

Bug: crates_vendor with cargo patch fails due to incorrect path resolution in local_crate_mirror.bzl

Open
#3,682 0 comments 0 reactions 0 assignees View on GitHub
bug crate-universe needs-triage
Dominant language
Starlark
Stars
843
Forks
651
Avg merge
2d 18h
Merged PRs (30d)
15

Description

# Bug: crates_vendor with cargo patch fails due to incorrect path resolution in local_crate_mirror.bzl

## Summary

When using `crates_vendor` with `mode = "remote"` and `Cargo.toml` with `[patch.crates-io]` sections that reference local vendor directories, the build fails with a path resolution error in `local_crate_mirror.bzl`. The issue is on line 9 where `repository_ctx.path(path)` resolves relative to the external repository instead of the workspace root.

## Environment

- **rules_rust version**: 0.55.0 (latest)
- **Bazel version**: 7.4.1 (via Bazelisk)
- **Operating system**: macOS
- **Rust toolchain**: 1.82.0

## Error Message

```
Error in readdir: can't readdir(), not a directory: /private/var/tmp/_bazel_xiaoyishi/d2c3080cf0842704a4fcd706f6251fe8/external/crate_index__base64-0.22.1/third_party/rust/vendor/base64-0.22.1
```

## Minimal Reproduction

**Repository**: https://github.com/ashi009/rules_rust_local_mirror_bug

### Steps to Reproduce

1. Clone the repository: `git clone https://github.com/ashi009/rules_rust_local_mirror_bug.git`
2. Run: `bazel run //third_party/rust:update-repo` (succeeds)
3. Run: `bazel build //third_party/rust/crates:base64` (fails with error above)

### Key Configuration Files

**Cargo.toml** with local patch:
```toml
[package]
name = "rules_rust_local_mirror_bug"
version = "0.1.0"
edition = "2021"

[dependencies]
base64 = "0.22.1"

[patch.crates-io]
base64 = { path = "third_party/rust/vendor/base64-0.22.1" }
```

**third_party/rust/BUILD.bazel** with crates_vendor:
```bzl
crates_vendor(
name = "crates",
annotations = {},
cargo_lockfile = "//:Cargo.lock",
manifests = ["//:Cargo.toml"],
mode = "remote",
repository_name = "third_party_rust",
tags = ["manual"],
vendor_path = "third_party/rust/vendor",
)
```

## Root Cause Analysis

The bug is in `crate_universe/private/local_crate_mirror.bzl` line 9:

```bzl
# Current (broken) code:
path = repository_ctx.path(repository_ctx.attr.path)

# The issue: repository_ctx.path(path) resolves relative to external repository
# but the path "third_party/rust/vendor/base64-0.22.1" should resolve relative to workspace root
```

When `crates_vendor` processes the cargo patch with `path = "third_party/rust/vendor/base64-0.22.1"`, it tries to resolve this path within the external repository context instead of the workspace root, leading to the incorrect path resolution.

## Proposed Fix

Replace the relative path resolution with workspace root resolution:

```bzl
# Fixed code:
path = repository_ctx.workspace_root.get_child(repository_ctx.attr.path)
```

This ensures that cargo patch paths are resolved relative to the workspace root where the `Cargo.toml` file is located, matching cargo's expected behavior.

## Impact

This bug affects any project using:
- `crates_vendor` with `mode = "remote"`
- `Cargo.toml` with `[patch.crates-io]` sections pointing to local paths
- Local vendor directories for dependency patching

This is a common pattern for organizations that need to patch dependencies locally while using `crates_vendor` for remote BUILD file generation.

## Workaround

Currently, there is no known workaround. The issue prevents using local cargo patches with `crates_vendor` in remote mode.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.