Universal-Debloater-Alliance/universal-android-debloater-next-generation · error
There must be 1 tab after serial
Error message
There must be 1 tab after serial
What it means
The devices function parses output of `adb devices -l`-style lines and expects each device line to contain a tab separating the serial from the status. If a line has no '\t', expect panics with "There must be 1 tab after serial". The library assumes well-formed adb output; any deviating line breaks this invariant.
Solutions
- Ensure no daemon-start banner is captured: run `adb start-server` once before calling devices().
- Verify the adb binary on PATH is the official platform-tools adb (check `which adb`).
- Filter adb output lines before parsing to only those containing '\t'.
- Upgrade the library / patch devices() to skip non-device lines instead of expecting a tab.
Example fix
// before
let tab_idx = dev_stat.find('\t').expect("There must be 1 tab after serial");
// after
let Some(tab_idx) = dev_stat.find('\t') else { continue; }; // skip banner/header lines Defensive patterns
Strategy: validation
Validate before calling
let output = std::process::Command::new("adb").args(["devices"]).output()?;
let has_device_line = String::from_utf8_lossy(&output.stdout)
.lines().any(|l| l.contains('\t')); Type guard
fn is_device_line(line: &str) -> bool { line.contains('\t') && !line.starts_with("List of") && !line.trim_start().starts_with('*') } Try / catch
let devices = std::panic::catch_unwind(|| adb::devices()).unwrap_or_else(|_| { eprintln!("malformed adb output; is adb on PATH?"); Vec::new() }); Prevention
- Run `adb start-server` before programmatic use to avoid daemon banner lines.
- Ensure the official platform-tools adb is first on PATH (no aliases/wrappers).
- Skip lines without a tab rather than assuming all lines are device entries.
- Pin/test against the adb version shipped with your toolchain.
When it happens
Trigger: Calling devices() when `adb devices` emits a line without a tab — e.g. the header lines "List of devices attached" or a trailing "* daemon not running..." message, or `adb` not being the real adb binary on PATH.
Common situations: First adb invocation starting the daemon (status lines interleaved), adb wrappers printing different formatting, custom/aliased adb on PATH, localized adb output.
Related errors
- There must be at least 1 ':'-separated component
- string assumed to be UID numeral
- {e}
- Could not write config file to disk!
- Can't detect config dir
AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12).
Data as JSON: /api/errors/580618bc988b6e98.
Report an issue: GitHub.
Appendix: source
Thrown at crates/uad-core/src/adb.rs:123
/// - TCP/IP: WIFI, Ethernet, etc...
/// - Local emulators
///
/// Status can be (but not limited to):
/// - "unauthorized"
/// - "device"
pub fn devices(mut self) -> Result<Vec<(String, String)>, String> {
self.0.arg("devices");
Ok(self
.run()?
.lines()
.skip(1) // header
.map(|dev_stat| {
let tab_idx = dev_stat
// OS-specific?
.find('\t')
// True on Linux,
// no matter if ADB is piped or connected to terminal
.expect("There must be 1 tab after serial");
(
// serial
dev_stat[..tab_idx].to_string(),
// status
dev_stat[(tab_idx + 1)..].to_string(),
)
})
.collect())
}
/// `version` sub-command
///
/// ## Format
/// This is just a sample,
/// we don't know which guarantees are stable (yet):
/// ```txt
/// Android Debug Bridge version 1.0.41
/// Version 34.0.5-debianView on GitHub (pinned to 64465c850c)