{"record":{"id":"d1865d23c15ad4dd","repo":"windmill-labs/windmill","slug":"get-assets-graph-res-status-await-res-tex","errorCode":null,"errorMessage":"GET assets/graph -> ${res.status}: ${await res.text()}","messagePattern":"GET assets/graph -> (.+?): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/pipeline/docs.ts","lineNumber":41,"sourceCode":"} from \"./localGraph.ts\";\n\nconst ASSET_KINDS = \"s3object,ducklake,datatable,volume,dbt\";\n\nfunction assetUri(kind: string, p: string): string {\n  const prefix = kind === \"s3object\" ? \"s3\" : kind;\n  return `${prefix}://${p}`;\n}\n\nasync function fetchDeployedGraph(\n  workspaceId: string,\n  folder: string,\n): Promise<AssetGraph> {\n  const res = await fetch(\n    `${OpenAPI.BASE}/w/${workspaceId}/assets/graph?folder=${encodeURIComponent(folder)}&asset_kinds=${ASSET_KINDS}`,\n    { headers: { Authorization: `Bearer ${OpenAPI.TOKEN}` } },\n  );\n  if (!res.ok) {\n    throw new Error(`GET assets/graph -> ${res.status}: ${await res.text()}`);\n  }\n  return hideDbtRunnables((await res.json()) as AssetGraph);\n}\n\n// Render the pipeline graph as a markdown document.\nexport function generatePipelineMarkdown(\n  folder: string,\n  graph: AssetGraph,\n  datatableSchemas: any[],\n  local: boolean,\n): string {\n  const writesByScript = new Map<string, string[]>();\n  const readsByScript = new Map<string, string[]>();\n  for (const e of graph.edges) {\n    if (e.runnable_kind !== \"script\") continue;\n    const uri = assetUri(e.asset_kind, e.asset_path);\n    if (e.access_type === \"w\" || e.access_type === \"rw\") {\n      (writesByScript.get(e.runnable_path) ?? writesByScript.set(e.runnable_path, []).get(e.runnable_path)!).push(uri);","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/pipeline/docs.ts#L23-L59","documentation":"Thrown by fetchDeployedGraph in the Windmill CLI pipeline docs tooling when the raw GET to `/w/{workspaceId}/assets/graph` returns a non-OK HTTP status. The error message includes the status code and the response body so the server-side reason (auth, bad folder, unsupported asset_kinds parameter) is surfaced directly.","triggerScenarios":"Calling `wmill pipeline docs/graph` against a workspace whose backend does not expose the assets/graph endpoint (older server), with an invalid or expired bearer token (401), a folder that does not exist, or a transient 5xx from the server.","commonSituations":"CLI version newer than the connected Windmill server (endpoint not yet deployed); WMILL_TOKEN expired or scoped to a different workspace; a typo'd/nonexistent --folder; corporate proxy returning 502/503.","solutions":["Check the status code and body in the message: 401/403 -> re-authenticate (`wmill auth login` or refresh WMILL_TOKEN).","404 -> verify the folder name and confirm the server version supports the /assets/graph endpoint; upgrade the server if it predates the feature.","5xx -> retry later or check the server logs; if behind a proxy, test the same request with curl to isolate it.","Confirm OpenAPI.BASE points at the intended instance (check --base-url / WMILL_BASE_URL)."],"exampleFix":"// before: stale token\nexport WMILL_TOKEN=eyJhbGciOi...expired\n\n// after\nwmill auth login --token <fresh-token> --workspace <ws>","handlingStrategy":"retry","validationCode":"const base = OpenAPI.BASE;\nif (!base) throw new Error(\"Set WMILL_BASE_URL / run `wmill auth login` before fetching the graph\");","typeGuard":null,"tryCatchPattern":"try {\n  const graph = await fetchDeployedGraph(workspaceId, folder);\n} catch (e: any) {\n  const m = /-> (\\d{3}):/.exec(e.message);\n  if (m && [\"502\", \"503\", \"504\"].includes(m[1])) {\n    await sleep(2000); // transient server/proxy error — retry\n  } else if (m && (m[1] === \"401\" || m[1] === \"403\")) {\n    console.error(\"Token expired or unauthorized — run `wmill auth login`\");\n  }\n  throw e;\n}","preventionTips":["Confirm the server version supports /assets/graph before upgrading the CLI past it.","Verify the folder name exists in the target workspace before fetching its graph.","Reproduce failing requests with curl and the same bearer token to isolate auth vs server issues."],"tags":["network","http","cli"],"backgroundTag":"http-request-failed","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}