Skip to content

Auto-update falsely reports failure on WSL Ubuntu - cold package prepare (~2m 27s) exceeds hardcoded 120s timeout #353

Description

@vojvojtech

Environment

  • OS: WSL Ubuntu (Windows 11)
  • kbagent version: 0.46.1 → 0.47.1

Root cause

The startup auto-update hook uses a hardcoded 120s timeout for the uv tool install --upgrade git+... subprocess (auto_update.py, _perform_update). On WSL Ubuntu with a cold uv package cache, preparing all 46 packages takes ~2m 27s. The subprocess is killed at 120s → TimeoutExpired → returns False → "Auto-update failed" is printed. On the next invocation with a warm cache, the update succeeds instantly — confirming the problem is purely the timeout, not a genuine install failure.


Bug 1 — False failure on cold cache

Reproduction:

# Seed a cold cache at v0.46.1
uv tool install git+https://github.com/keboola/cli@v0.46.1 --reinstall

kbagent doctor
# → "Updating kbagent v0.46.1 -> v0.47.1..."
# → "Auto-update failed; continuing with current version."

# Run again (warm cache) — now it succeeds
kbagent doctor
# → "Updating kbagent v0.46.1 -> v0.47.1..."
# → "Updated to v0.47.1. Re-launching..."

Key evidence from the cold-cache uv reinstall:

Prepared 46 packages in 2m 27s   ← exceeds hardcoded 120s

Bug 2 — kbagent update reports "already up to date" when it isn't

During the same session, after auto-update failed, running kbagent update returned:

kbagent v0.46.1 (already up to date)

…while kbagent --version confirmed it was still on v0.46.1 and v0.47.1 was available. The explicit update command silently reported wrong state instead of retrying.


Bug 3 — kbagent --json update startup hook and subcommand disagree

When running kbagent --json update, the startup hook fires (because argv[1] is --json, not update) and prints "Auto-update failed". But the explicit update subcommand runs afterward and returns JSON with "updated": true:

{
  "kbagent": {
    "updated": true,
    "current_version": "0.46.1",
    "latest_version": "0.47.1",
    "message": "Updated kbagent from v0.46.1 to v0.47.1. Restart your shell to use the new version."
  }
}

Same process, same invocation: human output says failure, machine output says success. Any script parsing the JSON exit would believe the update succeeded; any human reading the terminal would believe it failed.

This also exposes the argv[1] check issue: kbagent --json update triggers the startup hook, but kbagent update does not.


Suggested fixes

Short-term: Raise the timeout in _perform_update from 120s to at least 300s, or extract it as a named constant UPDATE_TIMEOUT_SECONDS.

Medium-term: Run the install in a background process and print "Update downloading in background — restart your shell when done." CLI is never blocked regardless of network/cache state.

For Bug 2 & 3: The "already up to date" check and the argv[1] check for skipping the startup hook both need reviewing — they interact badly when the previous auto-update silently failed.


Full terminal sessions

Session 1 — cold cache, false failures, JSON discrepancy
vojta@NTB:~$ kbagent doctor
Updating kbagent v0.46.1 -> v0.47.1...
Auto-update failed; continuing with current version.
Updating keboola-mcp-server v1.61.3 -> v1.63.1 (via uv_tool)...
Updated keboola-mcp-server to v1.63.1.
╭─────────────────────────────────────────────────── kbagent doctor 
[... doctor output omitted, checks passed ...]
────────────────────────────────────────╯
vojta@NTB:~$ kbagent doctor
Updating kbagent v0.46.1 -> v0.47.1...
Auto-update failed; continuing with current version.
╭─────────────────────────────────────────────────── kbagent doctor 
[... doctor output omitted, checks passed ...]
────────────────────────────────────────╯
vojta@NTB:~$ kbagent update
kbagent v0.46.1 (already up to date) | keboola-mcp-server v1.63.1 (already up to date)
vojta@NTB:~$ kbagent --version
kbagent v0.46.1
vojta@NTB:~$ kbagent --json update
Updating kbagent v0.46.1 -> v0.47.1...
Auto-update failed; continuing with current version.
{
  "status": "ok",
  "data": {
    "kbagent": {
      "updated": true,
      "current_version": "0.46.1",
      "latest_version": "0.47.1",
      "message": "Updated kbagent from v0.46.1 to v0.47.1. Restart your shell to use the new version.",
      "output": ""
    },
    "mcp": {
      "updated": false,
      "current_version": "1.63.1",
      "latest_version": "1.63.1",
      "install_method": "uv_tool",
      "message": "keboola-mcp-server v1.63.1 is already up to date."
    },
    "updated": true,
    "message": "kbagent v0.46.1 -> v0.47.1 | keboola-mcp-server v1.63.1 (already up to date)"
  }
}
Session 2 — reinstall to cold cache, warm-cache success proof
vojta@NTB:~$ kbagent --version
kbagent v0.47.1
vojta@NTB:~$ kbagent doctor
╭─────────────────────────────────────────────── kbagent doctor 
[... doctor output omitted, checks passed ...]
────────────────────────────────╯
vojta@NTB:~$ uv tool install git+https://github.com/keboola/cli@v0.46.1 --reinstall
Resolved 46 packages in 453ms
      Built keboola-agent-cli @ git+https://github.com/keboola/cli@a16fe57d12d373627621b7d49506c0b22e231669
Prepared 46 packages in 2m 27s
Uninstalled 46 packages in 196ms
Installed 46 packages in 75ms
 ~ annotated-doc==0.0.4
 ~ annotated-types==0.7.0
 ~ anyio==4.13.0
 ~ attrs==26.1.0
 ~ certifi==2026.5.20
 ~ cffi==2.0.0
 ~ click==8.4.1
 ~ croniter==6.2.2
 ~ cryptography==48.0.0
 ~ h11==0.16.0
 ~ httpcore==1.0.9
 ~ httpx==0.28.1
 ~ httpx-sse==0.4.3
 ~ idna==3.16
 ~ jsonschema==4.26.0
 ~ jsonschema-specifications==2025.9.1
 ~ kai-client==0.12.0
 - keboola-agent-cli==0.47.1 (from git+https://github.com/keboola/cli@2f80aaa7c4f0827fcae48e8bd472925e99e54b2c)
 + keboola-agent-cli==0.46.1 (from git+https://github.com/keboola/cli@a16fe57d12d373627621b7d49506c0b22e231669)
 ~ markdown-it-py==4.2.0
 ~ mcp==1.27.1
 ~ mdurl==0.1.2
 ~ packaging==26.2
 ~ platformdirs==4.9.6
 ~ prompt-toolkit==3.0.52
 ~ pycparser==3.0
 ~ pydantic==2.13.4
 ~ pydantic-core==2.46.4
 ~ pydantic-settings==2.14.1
 ~ pygments==2.20.0
 ~ pyjwt==2.13.0
 ~ python-dateutil==2.9.0.post0
 ~ python-dotenv==1.2.2
 ~ python-multipart==0.0.29
 ~ pyyaml==6.0.3
 ~ referencing==0.37.0
 ~ rich==15.0.0
 ~ rpds-py==0.30.0
 ~ shellingham==1.5.4
 ~ six==1.17.0
 ~ sse-starlette==3.4.4
 ~ starlette==1.1.0
 ~ typer==0.26.2
 ~ typing-extensions==4.15.0
 ~ typing-inspection==0.4.2
 ~ uvicorn==0.48.0
 ~ wcwidth==0.7.0
warning: The package `typer==0.26.2` does not have an extra named `all`
Installed 1 executable: kbagent
vojta@NTB:~$ kbagent doctor
Updating kbagent v0.46.1 -> v0.47.1...
Updated to v0.47.1. Re-launching...
  What's new in v0.47.1:
    - Fix (`storage create-table --if-not-exists`, keboola/cli#349): the `action: "skipped"` envelope now reports the EXISTING table's actual schema instead of re-echoing the caller's request. Pre-0.47.1, `columns` / `primary_key` / `name` on a skip mirrored the args the caller passed in, so a caller probing the skipped envelope to discover the real shape of a pre-existing table got the wrong values whenever the existing table differed from the request. The `get_table_detail(target_id)` lookup that already runs to confirm the table exists is now also the source of the returned schema. The caller's requested values are preserved under two new fields, `requested_columns` and `requested_primary_key`, and a new `schema_drift: bool` flags when the existing table diverges from the request (set comparison on columns and primary key). Human-mode output prints the actual schema on a skip and emits a `Warning:` line when `schema_drift` is true. `action: "created"` envelope is unchanged. No new flag, no signature change. Tests: `tests/test_storage_write.py` (skipped returns actual schema, drift flag set on divergence, no drift on match, human-mode warning render); `tests/test_e2e.py::TestE2E_0_47_0_NewSurfaces` extended to assert the skipped envelope reports actual columns + `requested_*` mirror.
╭─────────────────────────────────────────────── kbagent doctor 
[... doctor output omitted, checks passed ...]
────────────────────────────────╯

Note: In Session 2, after manually reinstalling to v0.46.1 with --reinstall (which cached all 46 packages as a side effect), the very next kbagent doctor succeeded immediately. This confirms the failure in Session 1 was purely the cold-cache prepare time (~2m 27s) exceeding the 120s timeout — not a genuine install problem.

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