Skip to content

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

@ashi009

Description

@ashi009

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:

[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:

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:

# 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:

# 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions