{"record":{"id":"2e073a35ab55d289","repo":"windmill-labs/windmill","slug":"failed-to-fetch-resource-types-from-hub","errorCode":null,"errorMessage":"Failed to fetch resource types from hub: {}","messagePattern":"Failed to fetch resource types from hub: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/src/main.rs","lineNumber":450,"sourceCode":"        skip_serializing_if = \"Option::is_none\"\n    )]\n    pub format_extension: Option<Option<String>>,\n}\n\nconst HUB_RT_CACHE_FILE: &str = \"resource_types.json\";\n\nasync fn cache_hub_resource_types() -> anyhow::Result<()> {\n    println!(\"Caching resource types from hub...\");\n\n    let response = HTTP_CLIENT\n        .get(format!(\"{}/resource_types/list\", DEFAULT_HUB_BASE_URL))\n        .header(\"Accept\", \"application/json\")\n        .send()\n        .await\n        .with_context(|| \"Failed to fetch resource types from hub\")?;\n\n    if !response.status().is_success() {\n        anyhow::bail!(\n            \"Failed to fetch resource types from hub: {}\",\n            response.status()\n        );\n    }\n\n    let raw_types: Vec<HubResourceTypeRaw> = response\n        .json::<Vec<HubResourceTypeRaw>>()\n        .await\n        .with_context(|| \"Failed to parse resource types from hub\")?;\n\n    // Parse schema strings into JSON values\n    let resource_types: Vec<HubResourceType> = raw_types\n        .into_iter()\n        .filter_map(|rt| {\n            let schema = match rt.schema {\n                Some(s) => match serde_json::from_str(&s) {\n                    Ok(v) => Some(v),\n                    Err(e) => {","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/src/main.rs#L432-L468","documentation":"At startup, Windmill's main caches hub resource types by fetching them from hub.windmill.dev. If the HTTP response returns a non-2xx status, the server bails with the upstream status code. This reflects a hub-side or network/gateway problem, not a local data problem.","triggerScenarios":"`cache_hub_resource_types` in windmill_main sends a GET with Accept: application/json to the hub and receives 4xx/5xx (404, 429, 502, 503, etc.).","commonSituations":"Hub outage or maintenance, rate limiting, corporate proxies/firewalls returning error pages, DNS hijacking captive portals, or a misconfigured hub base URL pointing at a non-hub host.","solutions":["Retry later; this is typically transient hub unavailability","Check network/proxy egress to hub.windmill.dev from the server host","Verify the hub base URL configuration if customized","Run with self-contained resource types or skip hub sync if the deployment allows offline mode"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let resp = loop {\n  match client.get(hub_url).header(\"Accept\", \"application/json\").send().await {\n    Ok(r) if r.status().is_success() => break r,\n    Ok(r) => { warn!(\"hub fetch failed: {}\", r.status()); }\n    Err(e) => warn!(\"hub fetch error: {e}\"),\n  }\n  tokio::time::sleep(Duration::from_secs(30)).await;\n};","preventionTips":["Monitor egress to hub.windmill.dev from the server","Wrap hub fetches with retry + backoff and a cached fallback","Alert on non-2xx hub responses at startup"],"tags":["http","network","hub","startup"],"backgroundTag":"http-4xx-5xx-response","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"}