fix: resolve provider icon sync failures (v1.6.1)#12
Merged
Conversation
Three bugs prevented provider icons from reliably appearing in the OpenWebUI model selector: 1. Wrong lookup order in _get_provider_icon: the hardcoded _PROVIDER_ICONS dict was always consulted before the dynamic OpenRouter registry. If OpenRouter changed any CDN path, the hardcoded (stale) URL was returned and served 404s while the registry — which always has current paths — was ignored for those providers. Fix: registry-first, hardcoded as fallback. 2. _provider_registry cached forever: a transient fetch failure at startup (network not ready, rate-limited, API hiccup) would leave the registry permanently empty until the pipe restarted. Non-200 responses were also silently ignored. Fix: added a 1h TTL (_PROVIDER_REGISTRY_TTL) and a log message for non-200s. 3. _icons_synced never reset: the set tracking "already synced" model IDs was never cleared between 5-minute model-cache refreshes. OWUI upserts models with the default data: icon after every pipes() call; the permanent _icons_synced state meant that any OWUI-overwritten icon was never restored. Fix: clear _icons_synced whenever the model cache is refreshed. Tests: 555 passed (6 new assertions covering the three fixes). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves provider icon reliability in the OpenRouter pipe by making icon resolution resilient to OpenRouter CDN path changes, transient registry fetch failures, and Open WebUI’s periodic model upserts that can overwrite icons.
Changes:
- Prefer OpenRouter’s live provider registry over the hardcoded
_PROVIDER_ICONSmapping when resolving provider icons. - Add a 1-hour TTL refresh to the cached provider registry and log non-200 registry responses.
- Clear
_icons_syncedon model cache refresh to ensure icons are re-synced after OWUI overwrites.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| openrouter_pipe.py | Adds provider registry TTL caching + logging, swaps icon lookup priority to registry-first, clears _icons_synced on model cache refresh. |
| test_pipe.py | Extends unit coverage for registry non-200 logging, TTL re-fetch behavior, and _icons_synced clearing semantics. |
| CHANGELOG.md | Documents v1.6.1 fixes related to provider icon syncing and registry caching behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2220
to
+2223
| # Expire cache and call pipes() again — _icons_synced must be cleared | ||
| _pipe_sync_clear._models_cache_ts = 0.0 | ||
| with patch.object(_pipe_sync_clear._session, "get", return_value=_mock_models_resp_sc): | ||
| _pipe_sync_clear.pipes() |
Comment on lines
1150
to
1186
| @@ -1153,28 +1171,37 @@ def _load_provider_registry(self) -> dict: | |||
| compact = slug.replace("-", "") | |||
| if compact and compact != slug: | |||
| registry.setdefault(compact, icon) | |||
| else: | |||
| print( | |||
| f"[OpenRouter Pipe] Provider registry returned HTTP " | |||
| f"{resp.status_code} — provider icons may be incomplete" | |||
| ) | |||
| finally: | |||
| resp.close() | |||
| except Exception as exc: # pragma: no cover | |||
| print(f"[OpenRouter Pipe] Provider registry fetch failed: {exc}") | |||
|
|
|||
| self._provider_registry = registry | |||
| self._provider_registry_ts = now | |||
| return registry | |||
On freshly-started CI runners time.monotonic() can be < 300 s, so setting _models_cache_ts = 0.0 left the cache appearing valid and the second pipes() call returned early without clearing _icons_synced. Subtract the full TTL + 1 from the stored timestamp instead so the cache is guaranteed expired regardless of system uptime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On a non-200 response or network exception _load_provider_registry() was
overwriting the cached registry with {} so any previously-resolved icons
would disappear for up to an hour.
Changes:
- Add _PROVIDER_REGISTRY_FAIL_TTL = 300 s (5 min) back-off constant
- Track `success` flag; only overwrite _provider_registry on HTTP 200
- On failure: preserve existing registry, apply FAIL_TTL back-off to
avoid retry storms while still recovering sooner than the full 1-hour TTL
- Updated docstring to document the failure-preservation semantics
- Extended tests 25l/25m to cover registry preservation and back-off retry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_get_provider_iconnow consults OpenRouter's live registry before the hardcoded_PROVIDER_ICONSdict. Previously, hardcoded URLs (verified May 2025) always won, meaning any CDN path change on OpenRouter's side would silently return 404s while the registry — which has always-current paths — was never reached for the 13 hardcoded providers._load_provider_registrypreviously cached the result forever; a single transient failure at startup (network not ready, 429, API hiccup) would leave the registry permanently empty until the pipe was restarted. The cache now expires after_PROVIDER_REGISTRY_TTL(1 hour) and re-fetches automatically. Non-200 responses now emit a[OpenRouter Pipe] Provider registry returned HTTP {status}log line so failures are diagnosable._icons_syncedcleared on model cache refresh — the "already synced" set was never reset between 5-minute model-cache cycles. OWUI upserts all models with the defaultdata:icon after everypipes()call; the permanent_icons_syncedstate meant any OWUI-overwritten icon was never restored until the pipe restarted. Clearing the set on every cache refresh ensures icons are re-synced and corrected each cycle.Root cause detail
Three independent bugs combined to make provider icons unreliable:
_icons_syncednever clearedFiles changed
openrouter_pipe.py—_PROVIDER_REGISTRY_TTLconstant,_provider_registry_tsfield,_load_provider_registryTTL + non-200 logging,_get_provider_iconorder,pipes()_icons_synced.clear()test_pipe.py— updated comments for 25k/25l, 3 new test sections (25m non-200 log, 25n TTL expiry re-fetch, 25o_icons_syncedclear)CHANGELOG.md— v1.6.1 entryTest plan
python test_pipe.py— 555 passed, 0 failed (6 new assertions)pipes()calls (~10 seconds after opening the model list)openrouter.aiin firewall) — check OWUI log forProvider registry returned HTTPorfetch failed; after unblocking, icons restore within 1 hour without pipe restart🤖 Generated with Claude Code