libnyanpasu/clash-nyanpasu · error
DIRECT is missing in /proxies
Error message
DIRECT is missing in /proxies
What it means
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.
Source
Thrown at backend/tauri/src/core/clash/proxies.rs:123
.filter(|(_k, v)| {
matches!(
v.vehicle_type,
api::VehicleType::Http | api::VehicleType::File
)
})
.collect()
};
// 2. Map every provider-owned proxy by name. Mihomo 1.19.28 no longer
// includes these nodes in /proxies, so their metadata must come from
// /providers/proxies.
let provider_map = provider_proxy_map(&providers_proxies);
let generate_item = |name: &str| resolve_proxy(name, &inner_proxies, &provider_map);
let global = inner_proxies.get("GLOBAL");
let direct = inner_proxies
.get("DIRECT")
.ok_or(anyhow::anyhow!("DIRECT is missing in /proxies"))?
.clone(); // It should be always exists
let reject = inner_proxies
.get("REJECT")
.ok_or(anyhow::anyhow!("REJECT is missing in /proxies"))?
.clone(); // It should be always exists
// 3. generate the proxies groups
let groups: Vec<ProxyGroupItem> = match global {
Some(api::ProxyItem { all: Some(all), .. }) => {
let all = all.clone();
all.into_iter()
.filter(|name| {
matches!(
inner_proxies.get(name),
Some(api::ProxyItem { all: Some(_), .. })
)
})
.map(|name| {View on GitHub (pinned to f7dbce2997)
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.
Example fix
// before
let proxies = Proxies::from_responses(proxies_res, providers_res)?;
// after
if !proxies_res.proxies.contains_key("DIRECT") {
anyhow::bail!("core /proxies response is not ready or malformed (missing DIRECT)");
}
let proxies = Proxies::from_responses(proxies_res, providers_res)?; Defensive patterns
Strategy: validation
Validate before calling
if !proxies_res.proxies.contains_key("DIRECT") {
anyhow::bail!("core /proxies not ready: missing DIRECT");
} Type guard
fn proxies_look_well_formed(res: &api::ProxiesRes) -> bool {
["DIRECT", "REJECT"].iter().all(|k| res.proxies.contains_key(*k))
} Try / catch
match Proxies::from_responses(proxies_res, providers_res) {
Ok(p) => p,
Err(e) if e.to_string().contains("DIRECT is missing") => {
// treat as core-not-ready; retry after delay
anyhow::bail!("core not ready, retry /proxies later: {e}")
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- REJECT is missing in /proxies
- Script mode is only available for Clash Premium
- unimplemented!()
- IPC server is already initialized
- application actor call timed out
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/8fe8e50f3fc7bee5.
Report an issue: GitHub.