Skip to content

fix(experiments): do not cache a failed npm lookup - #1787

Merged
Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/guesser-transient-cache-20261025
Oct 26, 2026
Merged

Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/guesser-transient-cache-20261025

Conversation

@rudycelekli

Copy link
Copy Markdown
Contributor

Bug

Guesser.checkNPMPackageWithClient (internal/experiments/guesser.go) writes its result to the cache manager on every exit path, including the failure paths: request errors, timeouts, non-200/404 statuses (5xx, 429), and an unparseable body. Those entries use the default 2h TTL, and the cache is checked before the network on the next call.

A failed lookup tells us nothing about whether the package exists, but it gets cached as exists: false. For two hours, every registry search that involves that repository loses its npm install_cmd / repository_info.

Trigger

The runtime's registry search (Runtime.SearchRegistryServers) builds a guesser with the shared cache manager. Batch lookups use a 3s client timeout. One slow npm response, a brief network drop or an npm 5xx during a search caches the failure. Refreshing the registry (RefreshRegistryCache) does not help, because it only drops the registry-servers: keys, while the guess entries live under npm:<package>.

Fix

Cache only the definitive answers: 200 (package found) and 404 (package does not exist). Failed lookups are returned without being cached, so the next search tries again.

Test

guesser_transient_cache_test.go drives checkNPMPackageWithClient with a scripted http.RoundTripper, so it makes no real network calls:

  • TestCheckNPMPackage_TransientFailureNotCached: the first response is a network error, a 503 or a 429, and the second is a 200. The second call must reach the transport and report the package as found.
  • TestCheckNPMPackage_DefinitiveAnswersCached: a 200 and a 404 are each still served from the cache on the second call.

Commands run

  • CGO_ENABLED=0 go test -count=1 -run 'TestCheckNPMPackage_(TransientFailureNotCached|DefinitiveAnswersCached)|TestGuesser_CacheEntriesAreStampedInternal|TestCaching|TestNilCacheManager' ./internal/experiments/: ok
  • CGO_ENABLED=0 go vet ./internal/experiments/: ok
  • On current main (and again with guesser.go reverted), all three TransientFailureNotCached subtests fail: expected: 2, actual: 1 transport calls, because the second call returned the cached failure.

checkNPMPackageWithClient cached every outcome for the 2h cache TTL,
including request errors, timeouts, 5xx and 429 responses. A single
failed lookup during a registry search hid the npm install hint for that
repository for two hours, and refreshing the registry cache did not help
because the guess entries live under their own npm: keys.

Cache only the definitive answers (200 and 404).
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dumbris Dumbris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: the PR test fails on main for the reason described and passes on this branch merged with main; race tests for the touched packages and CI lint (bare and server tags) are clean. Also built and tested together with the rest of this batch, independently reviewed, and cross-reviewed with a second model.

@Dumbris
Dumbris merged commit 9ac8a99 into smart-mcp-proxy:main Oct 26, 2026
46 checks passed
@Dumbris

Dumbris commented Oct 26, 2026

Copy link
Copy Markdown
Member

Merged. Thank you, @rudycelekli! A transient npm lookup failure is no longer cached as a permanent miss.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants