Skip to content

Fresh dependency resolution selects incompatible hts-sys bindings #665

Description

@SuhasSrinivasan

Summary

A fresh checkout of modkit at current upstream revision 5cecc3fb3a9336068d9e3c68d5c08d678153dd2c resolves rust-htslib 0.46.0 to hts-sys 2.2.1. Those generated/prebuilt binding shapes are incompatible with the API assumptions in rust-htslib 0.46.0, so an otherwise ordinary fresh build fails with ten Rust type/field errors.

The repository ignores and does not commit Cargo.lock, so successful builds can depend on when dependency resolution occurs even when modkit source and the Rust toolchain are unchanged.

Severity

Severity: High — build reproducibility and development reliability

Rationale: A fresh source build fails before modkit can be tested or installed. This is fully detectable and does not corrupt scientific output, but it blocks reproducible development, CI, packaging, and release builds from the same accepted source revision.

User and scientific impact

  • Affected result or workflow: building or testing modkit from a fresh checkout without a pre-existing lockfile.
  • Direction of error: deterministic compile failure after dependency resolution selects hts-sys 2.2.1.
  • Likely exposure: routine for new developers, clean CI/package builders, and any environment that regenerates the ignored lockfile.
  • Detectability or workaround: the failure is explicit; users can locally pin hts-sys to 2.2.0 or reuse a compatible lockfile, but neither workaround is encoded by the repository.

Affected versions and environment

  • Development revision: 5cecc3fb3a9336068d9e3c68d5c08d678153dd2c
  • modkit package version: 0.6.4
  • Operating system and architecture: macOS 26.6, arm64
  • Rust toolchain: rustc 1.90.0; cargo 1.90.0
  • Resolved dependency pair: rust-htslib 0.46.0 with hts-sys 2.2.1
  • Reproduced on: 2026-08-05 with a newly generated lockfile and fresh target directory

Steps to reproduce

Use a clean checkout so no ignored Cargo.lock from an earlier solve is present:

git clone https://github.com/nanoporetech/modkit.git modkit-fresh
cd modkit-fresh
git checkout 5cecc3fb3a9336068d9e3c68d5c08d678153dd2c

cargo generate-lockfile
cargo tree --locked -i hts-sys
cargo check --locked -p mod_kit

Control or independent oracle

On the same source and toolchain, constrain the workspace to hts-sys 2.2.0, regenerate the lockfile, and repeat the tree and check commands. The resolved graph should contain one hts-sys 2.2.0 instance shared by modkit and rust-htslib, and compilation should succeed.

Observed behavior

Fresh resolution reports:

hts-sys v2.2.1
└── rust-htslib v0.46.0
    ├── mod_kit v0.6.4
    ├── modkit v0.6.4
    ├── ochm v0.1.1
    └── safe-record v0.1.0

cargo check --locked -p mod_kit exits 101 after ten errors in rust-htslib 0.46.0. Representative failures are:

error[E0308]: mismatched types
  expected `usize`, found `u64`

error[E0609]: no field `isize` on type `bam1_core_t`
  help: a field with a similar name exists: `isize_`

error: could not compile `rust-htslib` (lib) due to 10 previous errors

The failing generated lockfile had SHA-256 4af98bb22a10b9b65b86e00a4d5831b254fc6aec89fd51931c5aefd2861d0f9a in the recorded reproduction.

Expected behavior

A fresh checkout at a fixed modkit revision should resolve one dependency graph that compiles and supports the repository test suite. Dependency resolution should not silently move rust-htslib 0.46.0 onto incompatible hts-sys bindings.

Root-cause evidence

  • The repository ignores the workspace lockfile at .gitignore:1-2.
  • mod_kit pins rust-htslib only to the compatible semver range beginning at 0.46.0 and has no hts-sys constraint at modkit-core/Cargo.toml:44-47.
  • rust-htslib 0.46.0 declares hts-sys 2.1.1 with caret semantics, which admits 2.2.1; the compile errors show that the 2.2.1 binding field/types no longer match rust-htslib 0.46.0's source assumptions.
  • Replacing only the resolved hts-sys version with 2.2.0 makes the same package and workspace checks succeed.

Proposed fix scope

Add an exact hts-sys = "=2.2.0" workspace dependency constraint next to rust-htslib in modkit-core/Cargo.toml. Cargo then unifies modkit and rust-htslib onto one compatible hts-sys 2.2.0 instance without changing Rust source or checked-in generated files.

This is a narrow compatibility pin that can be removed when modkit upgrades to a rust-htslib/hts-sys pair verified together.

Non-goals

  • No rust-htslib, HTSlib, BAM/CRAM behavior, or scientific-output change.
  • No decision in this fix about committing Cargo.lock for the binary workspace or requiring --locked in CI/install documentation.
  • No dependency-stack upgrade or broad version refresh.
  • No bindgen/libclang enablement or generated-binding changes.
  • No new CI workflow; the repository currently exposes no Rust PR test workflow.

Acceptance criteria

  • Fresh resolution at the fixed revision selects exactly one hts-sys 2.2.0 instance for the entire workspace.
  • cargo check --workspace --all-targets succeeds from a fresh target directory.
  • The complete workspace/all-targets test suite passes with no new failures.
  • The patch is limited to the exact compatibility constraint and explanatory comment.
  • No Cargo.lock, generated bindings, or unrelated dependency changes enter the diff.

Reproduction artifacts

Artifact Size SHA-256 Notes
Parent Cargo.lock generated, ignored 4af98bb22a10b9b65b86e00a4d5831b254fc6aec89fd51931c5aefd2861d0f9a Resolves hts-sys 2.2.1 and fails with ten errors
Fixed Cargo.lock generated, ignored d370908c0be24430282110489c8002550edd83a1811cf1bdc1dc68f972c01fc8 Resolves one hts-sys 2.2.0 instance; not part of the proposed diff

Related work

  • Related modkit issue or PR: none found by repository search.
  • Proposed PR: #666.
  • Upstream context: rust-htslib PR #514 updates current rust-htslib to hts-sys 2.2.1, but does not backport compatibility to modkit's rust-htslib 0.46.0; it is a possible long-term upgrade path, not a duplicate fix.
  • Deferred policy question: whether this binary workspace should commit Cargo.lock and make --locked part of CI/install workflows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions