libnyanpasu/clash-nyanpasu · error

uid-derived path is always a valid managed path

Error message

uid-derived path is always a valid managed path

What it means

This is a panic raised by `.expect()` when converting a uid-derived string into a `ManagedProfilePath` during profile item updates in the profiles actor. The code asserts that any path of the form `"{uid}.{ext}"` built from an existing profile uid and a canonical extension is always valid under the managed-path rules (non-empty, sane length, no illegal segments). If this expect fires, the uid/extension produced a path violating `ManagedProfilePath::new` invariants, which the actor treats as an unrecoverable internal bug, not a user error.

Source

Thrown at backend/tauri/src/state/profiles/actor.rs:1911

                }
            }
            ProfilesActorMessage::ReplaceDefinition {
                uid,
                definition,
                reply,
            } => {
                let versioned = state.manager.snapshot_handle().load();
                let expected_version = versioned.version;
                let before = versioned.state.clone();
                drop(versioned);
                let result = match before.items.get(&uid) {
                    None => Err(ProfilesError::ProfileNotFound(uid.clone())),
                    Some(previous_item) => {
                        let previous_source = previous_item.definition.source().cloned();
                        let mut definition = definition;
                        let ext = Self::canonical_extension(&definition);
                        let canonical = ManagedProfilePath::new(format!("{uid}.{ext}"))
                            .expect("uid-derived path is always a valid managed path");
                        let same_slot = match (&previous_source, definition.source()) {
                            (Some(previous), Some(next)) => {
                                Self::retains_materialization(previous, next, &canonical)
                            }
                            _ => false,
                        };
                        if let Some(source) = definition.source_mut() {
                            let materialized = source.materialized_mut();
                            materialized.file = canonical.clone();
                            materialized.updated_at = if same_slot {
                                previous_source
                                    .as_ref()
                                    .and_then(|source| source.materialized().updated_at)
                            } else {
                                None
                            };
                            if let ProfileSource::Remote { subscription, .. } = source {
                                *subscription = match (same_slot, previous_source.as_ref()) {

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Inspect the profile item's uid and its definition source extension; delete or repair the offending profile entry in the profiles config file.
  2. Check `ManagedProfilePath::new` validation rules and confirm `canonical_extension` sanitizes/whitelists the extension before composing the path.
  3. Upgrade/repair the profiles data via the app's own migration rather than feeding legacy definitions into the update path.
  4. If reproducible, file a bug with the profile definition that triggers it — this is an internal invariant violation, not a supported input state.

Example fix

// before
let canonical = ManagedProfilePath::new(format!("{uid}.{ext}"))
    .expect("uid-derived path is always a valid managed path");
// after
let canonical = ManagedProfilePath::new(format!("{uid}.{ext}"))
    .map_err(|e| ProfilesError::InvalidManagedPath(uid.clone(), e.to_string()))?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_uid_extension(uid: &str, ext: &str) -> Result<(), String> {
    if uid.is_empty() || ext.is_empty() {
        return Err("uid and extension must be non-empty".into());
    }
    let candidate = format!("{uid}.{ext}");
    ManagedProfilePath::new(candidate).map(|_| ()).map_err(|e| e.to_string())
}

Type guard

fn is_valid_managed_path(s: &str) -> bool {
    ManagedProfilePath::new(s.to_owned()).is_ok()
}

Try / catch

let canonical = ManagedProfilePath::new(format!("{uid}.{ext}"))
    .map_err(|e| ProfilesError::InvalidManagedPath(uid.clone(), e.to_string()))?;

Prevention

When it happens

Trigger: Calling the profile-item update path on the profiles actor (around actor.rs:1911) when a previous item lookup succeeded but `canonical_extension(&definition)` returns an extension containing path-illegal characters, or the uid itself is malformed/empty so the composed string fails `ManagedProfilePath::new` validation.

Common situations: A profile item persisted by an older app version carries a uid or source extension that fails newer path validation; a corrupted profiles.yaml or a hand-edited profile definition whose source yields a bogus extension (e.g. contains `/`, `..`, or is empty).

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/2b3b507736085e19. Report an issue: GitHub.