Skip to content

Outdated-version resolver may return stale "latest" transiently, unlike RegistryExistenceChecker #39

Description

@frankreyesgarcia

Summary

pkg/util/resolver/enrichment.go's EnrichmentResolver (used for the outdated-version comparison, via enrichment.NewClient(), which routes between ecosyste.ms and direct registry lookups) appears to be susceptible to the same kind of transient staleness that pkg/maven/existence.go's RegistryExistenceChecker was recently found to have for Maven's Solr-backed existence check - but, unlike RegistryExistenceChecker, it has no retry safeguard.

What happened

While running a pilot benchmarking yul against real projects from chains-project/bump (quickfixj, dependency org.apache.mina:mina-core, BUMP case 00a7cc31784ac4a9cc27d506a73ae589d6df36d6), Claude Code wrote mina-core from 2.1.5 to 2.2.4 and the PreToolUse hook let it through with no block.

2.2.4 is not the current latest release - 2.2.9 is. Confirmed two ways, moments after that run:

  • Querying resolver.EnrichmentResolver.LatestVersions directly for pkg:maven/org.apache.mina/mina-core returned 2.2.9.
  • Calling maven.Checker{Resolver: res, Existence: existence}.Check(before, after) directly for the exact same 2.1.52.2.4 pom.xml change correctly returned a mismatch: {org.apache.mina mina-core 2.2.4 2.2.9 KindOutdated}.

So the check is not deterministically broken - re-running it right afterward gives the correct answer. The most likely explanation is transient staleness in whatever backend enrichment.NewClient() resolved to at the exact moment of that specific hook invocation (ecosyste.ms sync lag, or the same kind of Solr search-index inconsistency that git-pkgs/registries has for Maven's core=gav responses - see git-pkgs/registries#82, which fixed a related but distinct decoding bug in that same client).

Why this is different from the existence-check fix

pkg/maven/existence.go's RegistryExistenceChecker.Existence now retries a registries.ErrNotFound, and separately a queried version missing from an otherwise-real version list, once (300ms backoff) before trusting either as a real negative - added specifically to smooth over this class of flakiness for the hallucination/existence check.

The outdated-version resolver has no equivalent. It's also less obviously retryable: existence has a clean "confirmed negative" signal to retry on (not found / not in list); "latest version" doesn't have as sharp a negative signal - a stale answer still looks like a valid, successful answer, just an out-of-date one. That needs some design thought before a retry (or a different mitigation, e.g. sanity-checking a resolved "latest" against a second source) could be added.

Suggested next steps

  • Decide whether/how to add a similar retry safeguard (or another mitigation) to EnrichmentResolver.LatestVersions / the enrichment.NewClient() path generally, given this affects every ecosystem's outdated check, not just Maven.
  • Consider whether this is worth reproducing more rigorously (e.g. a compare.go-style harness, like benchmark/hallucination/compare.go does for existence, but for "latest version" consistency across repeated calls).

Related

  • benchmark/bump/results/00a7cc31-mina-core.md - the pilot run that surfaced this (BUMP-based benchmarking of yul against real breaking-update projects).
  • pkg/maven/existence.go - the existence-check retry fix this is analogous to.
  • git-pkgs/registries#82 - the related (but distinct) upstream decoding bug fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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