Universal-Debloater-Alliance/universal-android-debloater-next-generation · error

There must be at least 1 ':'-separated component

Error message

There must be at least 1 ':'-separated component

What it means

list_users parses `adb shell pm list users` lines shaped like "UserInfo{0:Owner:13}[ running]" and splits on ':', expecting at least one component. If a line yields no first component (impossible for real input) the expect panics; effectively this fires when unexpected non-UserInfo lines reach the parser.

Solutions

  1. Check `adb shell pm list users` raw output on the affected device for format deviations.
  2. Ensure filtering only passes lines starting with 'UserInfo{' before parsing.
  3. Update the app/library for ROMs with a different user-info format.
  4. Patch to use if-let/next() with graceful skip instead of expect.

Example fix

// before
let id = comps.next().expect("There must be at least 1 ':'-separated component").parse().unwrap();
// after
let Some(id) = comps.next().and_then(|c| c.trim().parse().ok()) else { continue; };
Defensive patterns

Strategy: validation

Validate before calling

let output = std::process::Command::new("adb").args(["shell", "pm", "list", "users"]).output()?;
let ok = String::from_utf8_lossy(&output.stdout)
    .lines().any(|l| l.trim_start().starts_with("UserInfo{"));

Type guard

fn is_user_info_line(line: &str) -> bool { line.trim_start().starts_with("UserInfo{") }

Try / catch

let users = std::panic::catch_unwind(|| adb::list_users()).unwrap_or_else(|_| { eprintln!("unexpected pm list users output"); Vec::new() });

Prevention

When it happens

Trigger: Calling list_users() when adb output contains lines that pass the outer filter but lack the expected 'UserInfo{id:name:flags}' shape, e.g. empty/blank lines or warning text from adb shell.

Common situations: Non-standard Android ROMs altering pm list users format, adb daemon warnings inserted into output, OEM shells printing extra lines.

Related errors


AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12). Data as JSON: /api/errors/a1790b3751a7f3c7. Report an issue: GitHub.

Appendix: source

Thrown at crates/uad-core/src/adb.rs:418

                //let run;
                let ln = if let Some(l) = ln.strip_suffix("running") {
                    //run = true;
                    l.trim_ascii_end()
                } else {
                    //run = false;
                    ln
                };
                let ln = ln.strip_suffix('}').unwrap_or(ln).trim_ascii_end();
                // https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/core/java/android/content/pm/UserInfo.java
                // The format looks stable today, but google may change it in future Android versions
                // (and very old Androids might differ). Keep parsing defensive.
                // Expected shape: "UserInfo{<id>:<name>:<flags>}[ running]"

                let mut comps = ln.split(':');

                let id = comps
                    .next()
                    .expect("There must be at least 1 ':'-separated component")
                    .parse()
                    .expect("string assumed to be UID numeral");
                //let name = comps
                //    .next()
                //    .expect("There must be at least 2 ':'-separated components. 2nd is user-name");
                //let flags = u32::from_str_radix(
                //    comps.next().expect(
                //        "There must be at least 3 ':'-separated components. 3rd is user bit-flags",
                //    ),
                //    16,
                //)
                //.expect("string assumed to be hexadecimal bit-flags");
                UserInfo {
                    id,
                    //name: name.into(),
                    //flags,
                    //running: run,
                }

View on GitHub (pinned to 64465c850c)