{"record":{"id":"580618bc988b6e98","repo":"Universal-Debloater-Alliance/universal-android-debloater-next-generation","slug":"there-must-be-1-tab-after-serial","errorCode":null,"errorMessage":"There must be 1 tab after serial","messagePattern":"There must be 1 tab after serial","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/uad-core/src/adb.rs","lineNumber":123,"sourceCode":"    /// - TCP/IP: WIFI, Ethernet, etc...\n    /// - Local emulators\n    ///\n    /// Status can be (but not limited to):\n    /// - \"unauthorized\"\n    /// - \"device\"\n    pub fn devices(mut self) -> Result<Vec<(String, String)>, String> {\n        self.0.arg(\"devices\");\n        Ok(self\n            .run()?\n            .lines()\n            .skip(1) // header\n            .map(|dev_stat| {\n                let tab_idx = dev_stat\n                    // OS-specific?\n                    .find('\\t')\n                    // True on Linux,\n                    // no matter if ADB is piped or connected to terminal\n                    .expect(\"There must be 1 tab after serial\");\n                (\n                    // serial\n                    dev_stat[..tab_idx].to_string(),\n                    // status\n                    dev_stat[(tab_idx + 1)..].to_string(),\n                )\n            })\n            .collect())\n    }\n\n    /// `version` sub-command\n    ///\n    /// ## Format\n    /// This is just a sample,\n    /// we don't know which guarantees are stable (yet):\n    /// ```txt\n    /// Android Debug Bridge version 1.0.41\n    /// Version 34.0.5-debian","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/64465c850c7ed36329e67165ac08501abffb218e/crates/uad-core/src/adb.rs#L105-L141","documentation":"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.","triggerScenarios":"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.","commonSituations":"First adb invocation starting the daemon (status lines interleaved), adb wrappers printing different formatting, custom/aliased adb on PATH, localized adb output.","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."],"exampleFix":"// before\nlet tab_idx = dev_stat.find('\\t').expect(\"There must be 1 tab after serial\");\n// after\nlet Some(tab_idx) = dev_stat.find('\\t') else { continue; }; // skip banner/header lines","handlingStrategy":"validation","validationCode":"let output = std::process::Command::new(\"adb\").args([\"devices\"]).output()?;\nlet has_device_line = String::from_utf8_lossy(&output.stdout)\n    .lines().any(|l| l.contains('\\t'));","typeGuard":"fn is_device_line(line: &str) -> bool { line.contains('\\t') && !line.starts_with(\"List of\") && !line.trim_start().starts_with('*') }","tryCatchPattern":"let devices = std::panic::catch_unwind(|| adb::devices()).unwrap_or_else(|_| { eprintln!(\"malformed adb output; is adb on PATH?\"); Vec::new() });","preventionTips":["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."],"tags":["adb","parsing","panic","rust"],"backgroundTag":"unexpected-response-shape","analyzedSha":"64465c850c7ed36329e67165ac08501abffb218e","analyzedAt":"2026-09-12T09:09:23.137Z","contentChangedAt":"2026-09-12T09:09:23.137Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}