cube-js / cube-js/cube

Cube Cloud API reports an unusable REST URL for branch staging environments (/dev-mode/ + URL-encoded branch → 400 "Bad branch")

Open
#11,753 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
20.8k
Forks
2.1k
Avg merge
1d 2h
Merged PRs (30d)
181

Description

### Summary

For a branch **staging environment**, `GET /api/v1/deployments/{id}/environments` returns a REST
`api_credentials.url` that the deployment rejects with `400 BadRequestError: Bad branch`.

The URL that actually works is the one shown in the Cube Cloud UI. Two things differ:

| | Path segment | Branch in path |
| --- | --- | --- |
| API returns | `/dev-mode/` | URL-encoded (`team%2Fmy-branch`) |
| Works (and is what the UI shows) | `/staging/` | raw (`team/my-branch`) |

This surfaces through `cube environments list --json`, but it is **not** a CLI rendering
bug — the raw API response contains the same value (see below), so the CLI is faithfully
passing through what the API returns.

### Reproduction

1. Register a branch whose name contains a `/` (e.g. `team/my-branch`) on a deployment.
2. Enable its staging environment:
```
cube data-model enable-branch team/my-branch
```
3. Read the environment back:
```
cube environments list --json
```
```json
{
"branch": "team/my-branch",
"id": "",
"type": "staging",
"api_credentials": [
{
"type": "rest",
"url": "https://cube.example.com/dev-mode/team%2Fmy-branch/cubejs-api/v1",
"version": 1
}
]
}
```
4. Request `/meta` against that URL with a token from `cube deployments token `.

### Expected

The reported `url` serves the branch's data model.

### Actual

It returns `400`. Results for the same environment, same token:

| URL | Response |
| --- | --- |
| `/staging/team/my-branch/cubejs-api/v1/meta` | `200` — branch model |
| `/dev-mode/team%2Fmy-branch/cubejs-api/v1/meta` *(API-reported)* | `400 {"statusCode":400,"error":"BadRequestError: Bad branch"}` |
| `/staging/team%2Fmy-branch/cubejs-api/v1/meta` | `400 {"statusCode":400,"error":"BadRequestError: Bad branch"}` |
| `/cubejs-api/v1/meta` *(production, for comparison)* | `200` — production model |

The `/staging/` response returns a different cube count from production, confirming it is
genuinely serving the branch's model.

So neither substitution alone fixes the API-reported URL: the path segment must be `/staging/`
**and** the branch must not be URL-encoded.

### Not CLI-side

The same value comes back from the raw API, so this looks server-side rather than a CLI bug:

```
cube api GET /api/v1/deployments//environments
→ "url": "https://cube.example.com/dev-mode/team%2Fmy-branch/cubejs-api/v1"
```

### Why it matters

Anything programmatic — CI wiring a preview environment's cube URL into downstream services —
naturally trusts the URL the API reports for the environment it just enabled. That URL 400s, so
the correct behaviour is to *ignore* the API value and reconstruct
`/staging//cubejs-api/v1` by hand, which is fragile and non-obvious.

Also worth flagging as possibly related: the environment `type` is `staging` while the reported
path segment says `dev-mode`, which is confusing independent of the 400.

### Environment

- Cube CLI `1.7.33` (installed via `install-cli.sh`, `aarch64-apple-darwin`)
- Cube Cloud, `eu-west-2`
- Branch registered in Cube (not only in the connected git remote)

Deployment id, hostname and branch name are redacted; happy to supply them privately if useful.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing GET /api/v1/deployments//environments and compare its reported URL with the working Cube Cloud UI URL. Trace the environment URL construction and branch-path handling; done means staging environments return a usable /staging//cubejs-api/v1 URL that serves /meta successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.