-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
quay-v3.17.0
-
False
-
-
False
-
-
Summary
The new UI allows users to attempt setting tag expiration on organization mirror repositories, when these controls should be disabled upfront. The backend correctly rejects the request with HTTP 503, but users see a confusing generic error instead of being prevented from the action.
Current Behavior (Incorrect)
- User opens Tags tab for an org mirror repository (e.g., quayqe/repo216)
- UI displays tag expiration controls as enabled/clickable
- User attempts to set tag expiration
- Backend correctly rejects with HTTP 503: "Repository is in read only or mirror mode: ORG_MIRROR"
- UI shows generic error: "Could not set expiration for tag tag9: an unexpected issue occurred. Please try again or contact support"
Expected Behavior (Correct)
- UI detects repository state is ORG_MIRROR
- Tag expiration controls are disabled (grayed out)
- Informative tooltip explains: "Tag expiration is not supported for mirror repositories. Tags are managed by the source registry."
- User cannot attempt the action (prevented upfront)
Evidence
Screenshot shows:
- Enabled expiration controls on org mirror repo quayqe/repo216
- Generic error after backend rejection: "Could not set expiration for tag tag9"
- All tags show "Never" in Expires column (correct)
- User was able to click and attempt setting expiration (incorrect)
Technical Details
Backend (Working Correctly)
File: endpoints/api/tag.py:201-252
Endpoint: PUT /api/v1/repository/{namespace}/{repo}/tag/{tag}
Decorator: @disallow_for_non_normal_repositories (line 202)
Response: HTTP 503 with message "Repository is in read only or mirror mode: ORG_MIRROR"
def disallow_for_non_normal_repositories(func): @wraps(func) def wrapped(self, namespace_name, repository_name, *args, **kwargs): repo = data_model.repository.get_repository(namespace_name, repository_name) if repo and repo.state != RepositoryState.NORMAL: abort(503, message="Repository is in read only or mirror mode: %s" % repo.state) return func(self, namespace_name, repository_name, *args, **kwargs) return wrapped
Frontend (Bug)
Location: web/src/routes/RepositoryDetails/Tags/ (likely)
Issue: UI does not check repository state before enabling expiration controls
Impact: Poor UX - users attempt actions that will always fail
Repository States Requiring Disabled Controls
The following repository states should disable tag expiration controls:
- ORG_MIRROR - Organization mirror repositories
- MIRROR - Repository mirror
- READ_ONLY - Read-only repositories
- MARKED_FOR_DELETION - Deleted repositories
All these states are blocked by the backend decorator.
Recommended Fix
// Fetch repository details including state const repository = useRepository(namespace, repoName); // Disable expiration controls for non-NORMAL repos const expirationDisabled = repository.state !== 'NORMAL'; // Show informative tooltip const expirationTooltip = repository.state === 'ORG_MIRROR' ? "Tag expiration is not supported for mirror repositories. Tags are managed by the source registry." : repository.state === 'READ_ONLY' ? "Tag expiration cannot be modified on read-only repositories." : "Tag expiration controls are disabled for this repository.";
Severity
Medium - UX issue, not data corruption
- Backend correctly prevents invalid operations
- No data integrity risk
- Poor user experience (confusing error messages)
- Users may repeatedly attempt invalid actions
Acceptance Criteria
- UI detects repository state when loading Tags page
- Tag expiration controls disabled for ORG_MIRROR repositories
- Tag expiration controls disabled for MIRROR repositories
- Tag expiration controls disabled for READ_ONLY repositories
- Informative tooltip explains why controls are disabled
- No generic error shown when user attempts (prevented upfront)
- Behavior consistent across all repository types
Related Issues
- PROJQUAY-10040 - Organization mirror feature (original implementation)
- Backend protection already exists in endpoints/api/tag.py:202
Testing
- Create org mirror configuration
- Wait for repository discovery
- Navigate to Tags tab for mirrored repository
- Verify expiration controls are disabled
- Verify tooltip shows informative message
- Verify same behavior for MIRROR and READ_ONLY states
Additional Context
This bug was discovered during code review of organization mirror functionality. The backend correctly implements read-only enforcement for mirror repositories, but the UI allows users to attempt modifications that will always fail, creating a poor user experience.