Skip to content

Extensions: stale progress file causes wrong status after disable/uninstall #263

@yasinBursali

Description

@yasinBursali

Bug Report: Stale progress file causes wrong status after disable/uninstall

Severity: Medium
Category: Error Handling
Platform: All (macOS, Linux, Windows/WSL2)
Confidence: Confirmed (API-tested on macOS Apple Silicon)

Description

After installing an extension, the progress file persists through disable and uninstall operations. Because _compute_extension_status() checks progress files before checking actual extension state, a stale progress file overrides the real status. An uninstalled extension can show as "installing" in the UI.

Affected File(s)

  • dream-server/extensions/services/dashboard-api/routers/extensions.py (lines 103-128, 898-980, 983-1027)

Root Cause

The disable_extension() and uninstall_extension() endpoints do not clean up the progress file in data/extension-progress/{service_id}.json. The stale progress file (with status: "started") persists, and _compute_extension_status() checks it first (lines 103-128). Since _is_stale() uses a 300-second window for "started" status, the stale file takes priority over the actual extension state for up to 5 minutes.

The only cleanup mechanism is _cleanup_stale_progress() which runs lazily on catalog refresh and only removes files after 15 minutes (started) or 1 hour (other states).

Evidence

# _compute_extension_status checks progress FIRST (line 103-128)
progress = _read_progress(ext_id)
if progress:
    ps = progress.get("status", "")
    if ps == "started":
        if not _is_stale(progress.get("updated_at", ""), max_age_seconds=300):
            svc = services_by_id.get(ext_id)
            if not (svc and svc.status == "healthy"):
                return "installing"  # <-- returned even after uninstall!

Platform Analysis

  • macOS: Affected — confirmed via API testing
  • Linux: Affected — same Python code path
  • Windows/WSL2: Affected — same Python code path

Reproduction

  1. Install an extension: POST /api/extensions/chromadb/install
  2. Wait for status to show "enabled" or "installing"
  3. Disable: POST /api/extensions/chromadb/disable
  4. Check status: GET /api/extensions/chromadbshows "installing" instead of "disabled"
  5. Uninstall: DELETE /api/extensions/chromadb
  6. Check status: GET /api/extensions/chromadbshows "installing" instead of "not_installed"

Impact

  • Extension status is wrong in the UI for up to 5 minutes after disable/uninstall
  • Users see a spinner ("installing") for an extension they just removed
  • Confusing UX — user might think the operation failed

Suggested Approach

Delete the progress file in both disable_extension() and uninstall_extension() (and purge_extension_data()) after the operation completes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions