tikv/tikv · error

region must have leader

Error message

region must have leader

What it means

get_region_info returns region metadata including an Option<Leader>; None means the region currently has no leader (Raft has not elected one). split_region needs the leader to know which TiKV store to send the split request to, so it panics with 'region must have leader'.

Source

Thrown at cmd/tikv-ctl/src/main.rs:900

            ErrorKind::MissingRequiredArgument,
            "--pd is required for this command",
        );
    });
    let cfg = PdConfig::new(vec![pd]);
    cfg.validate().unwrap();
    RpcClient::new(&cfg, None, mgr).unwrap_or_else(|e| perror_and_exit("RpcClient::new", e))
}

fn split_region(pd_client: &RpcClient, mgr: Arc<SecurityManager>, region_id: u64, key: Vec<u8>) {
    let region = block_on(pd_client.get_region_by_id(region_id))
        .expect("get_region_by_id should success")
        .expect("must have the region");

    let leader = pd_client
        .get_region_info(region.get_start_key())
        .expect("get_region_info should success")
        .leader
        .expect("region must have leader");

    let store = pd_client
        .get_store(leader.get_store_id())
        .expect("get_store should success");

    let tikv_client = {
        let cb = ChannelBuilder::new(Arc::new(Environment::new(1)));
        let channel = mgr.connect(cb, store.get_address());
        TikvClient::new(channel)
    };

    let mut req = SplitRegionRequest::default();
    req.mut_context().set_region_id(region_id);
    req.mut_context()
        .set_region_epoch(region.get_region_epoch().clone());
    req.set_split_key(key);

    let resp = tikv_client

View on GitHub (pinned to 78aedc1c81)

Solutions

  1. Check the region's Raft status: `tikv-ctl raft log -r <region_id>` and verify peer states; wait for a leader to be elected and retry.
  2. Restore/downed TiKV stores first (`tikv-ctl --host <addr> ...`, check store states with pd-ctl `store`) so Raft can elect a leader.
  3. Re-fetch region info by key — if the region boundaries changed, target the new region ID instead.

Example fix

// before
.leader
.expect("region must have leader");
// after
let leader = match region_info.leader {
    Some(l) if l.get_id() != 0 => l,
    _ => { eprintln!("region has no leader yet; retry later"); return; }
};
Defensive patterns

Strategy: retry

Validate before calling

// confirm the region has a leader via pd-ctl before splitting
// pd-ctl region <region_id>  -> look for a non-empty "leader" field

Try / catch

// treat missing leader as transient: retry after leader election
for _ in 0..3 {
    if let Some(leader) = region_info.leader { break; }
    sleep(Duration::from_secs(2));
    region_info = refresh_region_info(...)?;
}

Prevention

When it happens

Trigger: Querying a region whose Raft group is in the middle of leader election, is down (all replicas unreachable), or is newly created/split and has not elected a leader yet; the region's start key no longer maps to the same region after concurrent splits/merges.

Common situations: Running split during a cluster incident with down TiKV stores; splitting a region right after a merge or split storm while elections are pending; querying regions on a store that was destroyed without proper offlining.

Related errors


AI-assisted analysis of tikv/tikv@78aedc1c81 (2026-09-03). Data as JSON: /api/errors/470ed7cbf4d762ec. Report an issue: GitHub.