Skip to content

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

@vojvojtech

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@NB-5BC34F3:~$ 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 ───────────────────────────────────────────────────╮
│   PASS  Config source: Using global config at /home/vojta/.config/keboola-agent-cli/config.json                      │
│   PASS  Config file: Config file exists at /home/vojta/.config/keboola-agent-cli/config.json with correct            │
│ permissions.                                                                                                         │
│   PASS  Config parseable: Config file is valid JSON with 14 project(s).                                              │
│   PASS  Project 'kosik-core': Connected to https://connection.eu-central-1.keboola.com (project: Kosik CORE, id:     │
│ 250) in 99ms                                                                                                         │                                                                                                │
│   PASS  CLI version: kbagent v0.46.1                                                                                 │
│   PASS  MCP server: MCP server available via: keboola_mcp_server (transport=stdio)                                   │
│   WARN  Conversation ID: KBAGENT_CONVERSATION_ID not set. API requests will not include X-Conversation-ID header.    │
│   PASS  Claude Code plugin: kbagent plugin v0.46.1 installed at                                                      │
│ /home/vojta/.claude/plugins/cache/keboola-agent-cli/kbagent/0.46.1                                                   │
│                                                                                                                      │
│   Summary: 21 checks, 20 passed, 1 warnings                                                                          │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
vojta@NB-5BC34F3:~$ kbagent doctor
Updating kbagent v0.46.1 -> v0.47.1...
Auto-update failed; continuing with current version.
╭─────────────────────────────────────────────────── kbagent doctor ───────────────────────────────────────────────────╮
│   PASS  Config source: Using global config at /home/vojta/.config/keboola-agent-cli/config.json                      │
│   PASS  Config file: Config file exists at /home/vojta/.config/keboola-agent-cli/config.json with correct            │
│ permissions.                                                                                                         │
│   PASS  Config parseable: Config file is valid JSON with 14 project(s).                                              │
│   PASS  Project 'kosik-core': Connected to https://connection.eu-central-1.keboola.com (project: Kosik CORE, id:     │
│ 250) in 123ms                                                                                                        │                                                                                               │
│   PASS  CLI version: kbagent v0.46.1                                                                                 │
│   PASS  MCP server: MCP server available via: keboola_mcp_server (transport=stdio)                                   │
│   WARN  Conversation ID: KBAGENT_CONVERSATION_ID not set. API requests will not include X-Conversation-ID header.    │
│   PASS  Claude Code plugin: kbagent plugin v0.46.1 installed at                                                      │
│ /home/vojta/.claude/plugins/cache/keboola-agent-cli/kbagent/0.46.1                                                   │
│                                                                                                                      │
│   Summary: 21 checks, 20 passed, 1 warnings                                                                          │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
vojta@NB-5BC34F3:~$ kbagent update
kbagent v0.46.1 (already up to date) | keboola-mcp-server v1.63.1 (already up to date)
vojta@NB-5BC34F3:~$ kbagent --version
kbagent v0.46.1
vojta@NB-5BC34F3:~$ 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@NB-5BC34F3:~$ kbagent --version
kbagent v0.47.1
vojta@NB-5BC34F3:~$ kbagent doctor
╭─────────────────────────────────────────────── kbagent doctor ───────────────────────────────────────────────╮
│   PASS  Config source: Using global config at /home/vojta/.config/keboola-agent-cli/config.json              │
│   PASS  Config file: Config file exists at /home/vojta/.config/keboola-agent-cli/config.json with correct    │
│ permissions.                                                                                                 │
│   PASS  Config parseable: Config file is valid JSON with 14 project(s).                                      │
│   PASS  Project 'kosik-core': Connected to https://connection.eu-central-1.keboola.com (project: Kosik CORE, │
│ id: 250) in 110ms                                                                                            │                                                                           │
│   PASS  CLI version: kbagent v0.47.1                                                                         │
│   PASS  MCP server: MCP server available via: keboola_mcp_server (transport=stdio)                           │
│   WARN  Conversation ID: KBAGENT_CONVERSATION_ID not set. API requests will not include X-Conversation-ID    │
│ header.                                                                                                      │
│   PASS  Claude Code plugin: kbagent plugin v0.46.1 installed at                                              │
│ /home/vojta/.claude/plugins/cache/keboola-agent-cli/kbagent/0.46.1 (CLI is v0.47.1 -- run `/plugin update    │
│ kbagent` in Claude Code to sync)                                                                             │
│                                                                                                              │
│   Summary: 21 checks, 20 passed, 1 warnings                                                                  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
vojta@NB-5BC34F3:~$ 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@NB-5BC34F3:~$ 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 ───────────────────────────────────────────────╮
│   PASS  Config source: Using global config at /home/vojta/.config/keboola-agent-cli/config.json              │
│   PASS  Config file: Config file exists at /home/vojta/.config/keboola-agent-cli/config.json with correct    │
│ permissions.                                                                                                 │
│   PASS  Config parseable: Config file is valid JSON with 14 project(s).                                      │
│   PASS  Project 'kosik-core': Connected to https://connection.eu-central-1.keboola.com (project: Kosik CORE, │
│ id: 250) in 96ms                                                                                             │                                                                           │
│   PASS  CLI version: kbagent v0.47.1                                                                         │
│   PASS  MCP server: MCP server available via: keboola_mcp_server (transport=stdio)                           │
│   WARN  Conversation ID: KBAGENT_CONVERSATION_ID not set. API requests will not include X-Conversation-ID    │
│ header.                                                                                                      │
│   PASS  Claude Code plugin: kbagent plugin v0.46.1 installed at                                              │
│ /home/vojta/.claude/plugins/cache/keboola-agent-cli/kbagent/0.46.1 (CLI is v0.47.1 -- run `/plugin update    │
│ kbagent` in Claude Code to sync)                                                                             │
│                                                                                                              │
│   Summary: 21 checks, 20 passed, 1 warnings                                                                  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions