windmill-labs/windmill · error · Error

GET ${path} -> ${response.status}: ${body}

Error message

GET ${path} -> ${response.status}: ${body}

What it means

Generic API error thrown by apiGet, the helper behind read-only `wmill pipeline` subcommands (list, show, etc.). Any non-OK response from `GET {OpenAPI.BASE}{path}` is converted into an Error carrying the request path, HTTP status, and response body, replacing the default fetch behavior of silently resolving.

Source

Thrown at cli/src/commands/pipeline/pipeline.ts:71

// GraphTrigger) are defined in ./localGraph.ts — the canonical pipeline graph
// module — and shared by the local (wasm-built) and deployed (apiGet) paths.
//
// Mirrors the asset-graph endpoint payload (backend/windmill-api-assets).
// TODO: the checked-in generated client (cli/gen, last regenerated 2025-04)
// predates these routes, so we raw-fetch and hand-roll the types. Once
// `cli/gen` is regenerated (run `cli/gen_wm_client.sh`, which is currently
// >700 openapi.yaml commits stale and would churn the whole client), replace
// `apiGet` + these types with the generated `wmill.getAssetsGraph(...)`
// (operationId getAssetsGraph) and `wmill.listPipelineFolders(...)`
// (operationId listPipelineFolders).

async function apiGet<T>(path: string): Promise<T> {
  const response = await fetch(`${OpenAPI.BASE}${path}`, {
    headers: { Authorization: `Bearer ${OpenAPI.TOKEN}` },
  });
  if (!response.ok) {
    const body = await response.text();
    throw new Error(`GET ${path} -> ${response.status}: ${body}`);
  }
  return (await response.json()) as T;
}

async function list(opts: GlobalOptions & { json?: boolean }) {
  if (opts.json) log.setSilent(true);
  const workspace = await resolveWorkspace(opts);
  await requireLogin(opts);

  const items = await apiGet<{ folder: string; script_count: number }[]>(
    `/w/${workspace.workspaceId}/assets/pipelines`,
  );
  if (opts.json) {
    console.log(JSON.stringify(items));
  } else if (items.length === 0) {
    log.info(
      "No pipelines in this workspace. Mark scripts with a `// pipeline` comment (plus `// on <spec>` triggers) and push them into a folder.",
    );

View on GitHub (pinned to e474e8803c)

Solutions

  1. Inspect status in the message: 401/403 -> run `wmill auth login` or fix WMILL_TOKEN/workspace.
  2. 404 -> verify the pipeline/script path and workspace id (`wmill workspace list`).
  3. Confirm the base URL with curl: `curl -H "Authorization: Bearer $WMILL_TOKEN" $WMILL_BASE_URL<path>` to reproduce outside the CLI.
  4. 5xx -> check server health/logs, then retry; if behind a proxy, verify it forwards Authorization headers.

Example fix

// before: hitting wrong instance
wmill pipeline list # -> GET /w/.../pipelines -> 404: ...

// after
wmill workspace switch <correct-workspace>
wmill pipeline list
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: verify auth and base URL before calling pipeline subcommands
const res = await fetch(`${OpenAPI.BASE}/users/me`, {
  headers: { Authorization: `Bearer ${OpenAPI.TOKEN}` },
});
if (!res.ok) throw new Error(`Auth/base-url check failed: ${res.status}`);

Try / catch

try {
  const items = await apiGet<Pipeline[]>(`/w/${ws}/pipelines/list`);
} catch (e: any) {
  const m = /-> (\d{3}):/.exec(e.message);
  switch (m?.[1]) {
    case "401": case "403": console.error("Run `wmill auth login`"); break;
    case "404": console.error("Unknown path/workspace — check `wmill workspace list`"); break;
    default: console.error("Server error — check instance health");
  }
  throw e;
}

Prevention

When it happens

Trigger: Any `wmill pipeline <subcommand>` where the backend returns 401 (missing/expired token), 404 (unknown pipeline/script path), 400 (malformed path), or 5xx; also when OpenAPI.BASE is misconfigured and hits the wrong host (404/502 from a proxy).

Common situations: Running without `wmill auth login` first; pipeline path with a typo or wrong workspace; targeting a self-hosted instance through a reverse proxy that mangles the path; server temporarily down returning 502.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/26ba48030c7fde7a. Report an issue: GitHub.