{"record":{"id":"8fe8e50f3fc7bee5","repo":"libnyanpasu/clash-nyanpasu","slug":"direct-is-missing-in-proxies","errorCode":null,"errorMessage":"DIRECT is missing in /proxies","messagePattern":"DIRECT is missing in /proxies","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/clash/proxies.rs","lineNumber":123,"sourceCode":"                .filter(|(_k, v)| {\n                    matches!(\n                        v.vehicle_type,\n                        api::VehicleType::Http | api::VehicleType::File\n                    )\n                })\n                .collect()\n        };\n\n        // 2. Map every provider-owned proxy by name. Mihomo 1.19.28 no longer\n        // includes these nodes in /proxies, so their metadata must come from\n        // /providers/proxies.\n        let provider_map = provider_proxy_map(&providers_proxies);\n        let generate_item = |name: &str| resolve_proxy(name, &inner_proxies, &provider_map);\n\n        let global = inner_proxies.get(\"GLOBAL\");\n        let direct = inner_proxies\n            .get(\"DIRECT\")\n            .ok_or(anyhow::anyhow!(\"DIRECT is missing in /proxies\"))?\n            .clone(); // It should be always exists\n        let reject = inner_proxies\n            .get(\"REJECT\")\n            .ok_or(anyhow::anyhow!(\"REJECT is missing in /proxies\"))?\n            .clone(); // It should be always exists\n\n        // 3. generate the proxies groups\n        let groups: Vec<ProxyGroupItem> = match global {\n            Some(api::ProxyItem { all: Some(all), .. }) => {\n                let all = all.clone();\n                all.into_iter()\n                    .filter(|name| {\n                        matches!(\n                            inner_proxies.get(name),\n                            Some(api::ProxyItem { all: Some(_), .. })\n                        )\n                    })\n                    .map(|name| {","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/clash/proxies.rs#L105-L141","documentation":"Thrown by `Proxies::from_responses` when the `/proxies` API response from the Clash/Mihomo core does not contain the built-in `DIRECT` proxy entry. The parser assumes every core always reports the built-in `DIRECT`/`REJECT`/`GLOBAL` nodes and destructures them with `ok_or`; a missing entry means the response is not a well-formed proxies payload, so the library fails instead of producing a Proxies struct with a hole in it.","triggerScenarios":"Calling `Proxies::from_responses(proxies_res, providers_res)` where `proxies_res.proxies` (deserialized from the core's `GET /proxies`) lacks a key literally named `\"DIRECT\"` — e.g. the endpoint returned an error object, a partial/empty map, or a non-standard core/modified API.","commonSituations":"Core not fully started or shutting down so /proxies returns an empty/partial map; pointing the client at the wrong port or a different service that speaks a different API; an external controller behind a proxy/CDN that rewrites the response; a core version or fork whose /proxies omits built-ins; deserializing the wrong endpoint body into ProxiesRes.","solutions":["Verify the core is running and the external controller URL/port is correct before fetching /proxies.","Inspect the raw /proxies response (curl the controller endpoint) and confirm it contains \"DIRECT\".","Retry after the core finishes starting; treat a missing DIRECT as a transient not-ready signal.","Check for a core version/fork that deviates from the standard API and update or switch cores."],"exampleFix":"// before\nlet proxies = Proxies::from_responses(proxies_res, providers_res)?;\n// after\nif !proxies_res.proxies.contains_key(\"DIRECT\") {\n    anyhow::bail!(\"core /proxies response is not ready or malformed (missing DIRECT)\");\n}\nlet proxies = Proxies::from_responses(proxies_res, providers_res)?;","handlingStrategy":"validation","validationCode":"if !proxies_res.proxies.contains_key(\"DIRECT\") {\n    anyhow::bail!(\"core /proxies not ready: missing DIRECT\");\n}","typeGuard":"fn proxies_look_well_formed(res: &api::ProxiesRes) -> bool {\n    [\"DIRECT\", \"REJECT\"].iter().all(|k| res.proxies.contains_key(*k))\n}","tryCatchPattern":"match Proxies::from_responses(proxies_res, providers_res) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"DIRECT is missing\") => {\n        // treat as core-not-ready; retry after delay\n        anyhow::bail!(\"core not ready, retry /proxies later: {e}\")\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Confirm the external controller URL/port/secret before polling /proxies","Wait for the core's ready signal before the first /proxies fetch","Inspect the raw /proxies JSON when debugging (curl the controller)","Avoid non-standard cores or middleware that rewrite the controller API"],"tags":["rust","clash","mihomo","api","proxies"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}