gitui-org/gitui · warning · anyhow::Error

no valid branch selected

Error message

no valid branch selected

What it means

switch_to_selected_branch() first calls valid_selection() and bails when the current selection is not a usable branch entry - the list is empty, the index no longer points at a live entry after the branch list changed (deletion, fetch refresh), or the kind of entry selected cannot be switched to in this mode.

Solutions

  1. Close and reopen the branch popup so the list rebuilds, then select an entry.
  2. Refresh repo state (fetch / press r) so deletions and new branches are reflected before switching.
  3. Clear the filter and confirm an entry is actually highlighted before pressing enter.
Defensive patterns

Strategy: validation

Validate before calling

// mirror the component's own guard before acting
if !branches.is_empty() && (selection as usize) < branches.len() && branch_kind_switchable(selection) {
    popup.switch_to_selected_branch()?;
}

Prevention

When it happens

Trigger: Pressing enter in the branch popup with nothing highlighted (fresh popup, all entries filtered out by the search); the selected branch deleted by another git process while the popup was open; selection index out of range after the list rebuilt.

Common situations: Stale popup after running git branch -D in another terminal; typing a filter that empties the list and hitting enter anyway; races between fetch-driven list updates and keypresses.

Related errors


AI-assisted analysis of gitui-org/gitui@2fa693cb6e (2026-08-16). Data as JSON: /api/errors/5d924beb142b316a. Report an issue: GitHub.

Appendix: source

Thrown at src/popups/branchlist.rs:582

				format!("{branch_name:branch_name_length$} "),
				theme.branch(selected, is_head),
			);

			txt.push(Line::from(vec![
				span_prefix,
				span_name,
				span_hash,
				span_msg,
			]));
		}

		Text::from(txt)
	}

	///
	fn switch_to_selected_branch(&mut self) -> Result<()> {
		if !self.valid_selection() {
			anyhow::bail!("no valid branch selected");
		}

		let status = sync::status::get_status(
			&self.repo.borrow(),
			StatusType::WorkingDir,
			None,
		)
		.expect("Could not get status");

		let selected_branch = &self.branches[self.selection as usize];
		if status.is_empty() {
			if self.local {
				checkout_branch(
					&self.repo.borrow(),
					&selected_branch.name,
				)?;
				self.hide();
			} else {

View on GitHub (pinned to 2fa693cb6e)