libnyanpasu/clash-nyanpasu · error
Invalid theme color: {}
Error message
Invalid theme color: {} What it means
patch_verge validates the optional theme_color field before applying an IVerge patch. If theme_color is set, non-empty, and not a strict '#RRGGBB' hex string (7 chars, '#' prefix, ASCII hex digits only — see is_hex_color in backend/tauri/src/config/nyanpasu/mod.rs:10), the patch is rejected with anyhow::bail and nothing is written.
Source
Thrown at backend/tauri/src/feat.rs:352
Config::clash().data().save_config()?;
Ok(rebuilt)
}
Err(err) => {
Config::clash().discard();
Err(err)
}
}
}
/// 修改verge的配置
/// 一般都是一个个的修改
pub async fn patch_verge(client: crate::client::NyanpasuClient, patch: IVerge) -> Result<()> {
// Validate theme_color if it's being updated
if let Some(ref theme_color) = patch.theme_color
&& !theme_color.is_empty()
&& !crate::config::nyanpasu::is_hex_color(theme_color)
{
anyhow::bail!("Invalid theme color: {}", theme_color);
}
Config::verge().draft().patch_config(patch.clone());
let tun_mode = patch.enable_tun_mode;
let auto_launch = patch.enable_auto_launch;
let system_proxy = patch.enable_system_proxy;
let proxy_bypass = patch.system_proxy_bypass;
let language = patch.language;
let log_level = patch.app_log_level;
let log_max_files = patch.max_log_files;
let enable_tray_selector = patch.clash_tray_selector;
let enable_tray_text = patch.enable_tray_text;
let tray_menu_mode = patch.tray_menu_mode;
let network_statistic_widget = patch.network_statistic_widget;
let res = || async move {
let service_mode = patch.enable_service_mode;
if let Some(service_mode) = service_mode {
log::debug!(target: "app", "change service mode to {}", service_mode);View on GitHub (pinned to f7dbce2997)
Solutions
- Normalize the value to a 7-character '#RRGGBB' hex string (uppercase or lowercase digits both pass) before calling patch_verge
- If the color is not a plain hex (named color, rgb(), 8-digit hex), convert it: expand #RGB to #RRGGBB and drop the alpha bytes
- Trim whitespace and confirm length is exactly 7 with a leading '#' before sending the patch
- If no theme change is intended, send patch with theme_color: None (or omit the field) instead of an empty or placeholder string
Example fix
// before
client.patch_verge(IVerge { theme_color: Some("#fff".into()), ..patch }).await?;
// after
let color = "#fff";
let normalized = if color.len() == 4 && color.starts_with('#') {
format!("#{0}{0}{1}{1}{2}{2}", &color[1..2], &color[2..3], &color[3..4])
} else { color.to_string() };
assert!(crate::config::nyanpasu::is_hex_color(&normalized));
client.patch_verge(IVerge { theme_color: Some(normalized), ..patch }).await?; Defensive patterns
Strategy: validation
Validate before calling
pub fn valid_theme_color(color: &str) -> bool {
color.len() == 7 && color.starts_with('#') && color[1..].chars().all(|c| c.is_ascii_hexdigit())
}
// call site
if let Some(c) = &patch.theme_color {
if !c.is_empty() && !valid_theme_color(c) { return Err(anyhow!("Invalid theme color: {}", c)); }
} Type guard
fn as_valid_theme_color(color: &Option<String>) -> Option<&str> {
color.as_deref().filter(|c| !c.is_empty() && c.len() == 7 && c.starts_with('#') && c[1..].chars().all(|c| c.is_ascii_hexdigit()))
} Try / catch
match client.patch_verge(patch).await {
Err(e) if e.to_string().starts_with("Invalid theme color") => {
log::warn("theme_color rejected, reverting to default");
client.patch_verge(IVerge { theme_color: None, ..patch }).await?;
}
other => other?,
} Prevention
- Always emit colors from the UI as #RRGGBB; expand 3-digit hex and strip alpha before patching
- Run is_hex_color (or an equivalent regex ^#[0-9a-fA-F]{6}$) at the form/input layer before submitting
- Trim and normalize user-entered colors before storing them in IVerge
- Omit theme_color (None) rather than sending empty or placeholder strings when no change is intended
When it happens
Trigger: Calling patch_verge (e.g. via the patch_verge_entrypoint Tauri command) with patch.theme_color = Some(value) where value is not exactly 7 characters of the form #RRGGBB: e.g. 'blue', '#fff', '#GGGGGG', 'rgb(255,0,0)', '#ffffff ' (trailing space), or a full-length '#RRGGBBAA' string.
Common situations: Frontend color pickers emitting lowercase names or 3-digit hex; a user typing a color manually into a config UI; switching from a theme that stored alpha-extended hex (#RRGGBBAA) or named colors; a migration/import importing an old verge config with non-hex theme_color; locale-sensitive input adding whitespace.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Invalid theme color: {}
- cannot repair typed clash config before split_legacy_config
- legacy mutation may have non-reversible side effects and req
- profiles.yaml failed validation: {errors:?}
- failed to parse config: {e}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/19a6152a11b581f3.
Report an issue: GitHub.