Skip to content

download-table fails with NOT_FOUND on dev branch tables (get_file_info missing branch prefix) #161

Description

@frantisekrehor

Summary

kbagent storage download-table fails with NOT_FOUND: File not found for any table on a dev branch. Root cause: the async export flow creates a Storage File scoped to the branch, but the follow-up get_file_info call queries the main project scope without a branch prefix.

Reproduction

Tested on kbagent v0.18.6, project databased (891), branch 15894.

# 1. Create branch (auto-activates)
kbagent --json branch create --project databased --name test-export-2026-04-14
# -> branch_id: 15894

# 2. Create bucket + table + upload data
kbagent --json storage create-bucket --project databased --stage in --name test-export-branch
kbagent --json storage create-table --project databased --bucket-id in.c-test-export-branch \
  --name test_data --column "id:INTEGER" --column "name:STRING" --primary-key id
kbagent --json storage upload-table --project databased \
  --table-id in.c-test-export-branch.test_data --file /tmp/test_data.csv
# -> imported_rows: 3, OK

# 3. Verify table exists with data
kbagent --json storage table-detail --project databased \
  --table-id in.c-test-export-branch.test_data
# -> rows_count: 3, columns listed OK

# 4. Download -> FAILS
kbagent --json storage download-table --project databased \
  --table-id in.c-test-export-branch.test_data --branch 15894 --output /tmp/out.csv

Returns:

{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found: File not found."
  }
}

Same failure reproduces with storage unload-table on a branch table.

Control: download-table on a production (main) table works fine:

kbagent --json storage download-table --project databased \
  --table-id in.c-data-based-ex-freelo-186733604.users --limit 5 --output /tmp/users.csv
# -> OK, file exported

Root cause

In keboola_agent_cli/client.py:

  1. export_table_async (line 1167) correctly prefixes the URL with the branch:

    prefix = f"/v2/storage/branch/{branch_id}" if branch_id else "/v2/storage"
    # POST {prefix}/tables/{safe_id}/export-async

    The Storage File is created in the branch scope.

  2. get_file_info (line 1199) does not accept branch_id and always queries main:

    def get_file_info(self, file_id: int) -> dict[str, Any]:
        response = self._request(
            "GET",
            f"/v2/storage/files/{file_id}",
            params={"federationToken": "1"},
        )

    → Storage API returns 404 because the file was created in the branch scope, not main.

  3. services/storage_service.py:604 calls client.get_file_info(file_id) without passing branch_id, so even if the client supported it, the service wouldn't use it.

Proposed fix

client.py:1199 — accept and use branch_id:

def get_file_info(self, file_id: int, branch_id: int | None = None) -> dict[str, Any]:
    prefix = f"/v2/storage/branch/{branch_id}" if branch_id else "/v2/storage"
    response = self._request(
        "GET",
        f"{prefix}/files/{file_id}",
        params={"federationToken": "1"},
    )
    return response.json()

services/storage_service.py:604 — pass branch through:

file_detail = client.get_file_info(file_id, branch_id=branch_id)

Other file endpoints in client.py (delete_file, tag_file, untag_file, list_files) likely have the same bug — worth auditing in the same PR.

Impact

Any workflow that tries to read/export data from a dev branch via kbagent CLI fails. Currently the only workaround is to merge the branch to main first, which defeats the purpose of dev branch isolation.

Environment

  • kbagent: v0.18.6
  • keboola-mcp-server: v1.49.1
  • Stack: connection.eu-central-1.keboola.com
  • Project: 891 (data-based internal)
  • Branch: 15894 (test-export-2026-04-14)

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