tikv/tikv · error · sst_importer::Error
download method only accepts single-file requests, use batch
Error message
download method only accepts single-file requests, use batch_download for multi-file requests
What it means
The legacy single-file download gRPC method rejects requests that carry a multi-file ssts set. The batch API (batch_download) exists for multi-file requests, so the single-file method guards against misuse and returns the error inside the DownloadResponse instead of failing the RPC.
Source
Thrown at src/import/sst_service.rs:1085
};
self.threads.spawn(handle_task);
}
/// Downloads the file and performs key-rewrite for later ingesting.
fn download(
&mut self,
_ctx: RpcContext<'_>,
req: DownloadRequest,
sink: UnarySink<DownloadResponse>,
) {
let label = "download";
IMPORT_RPC_COUNT.with_label_values(&[label]).inc();
let timer = Instant::now_coarse();
// download method only handles single file downloads
// Check that this is indeed a single-file request
if !req.get_ssts().is_empty() {
let error = sst_importer::Error::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"download method only accepts single-file requests, use batch_download for multi-file requests",
));
let mut resp = DownloadResponse::default();
resp.set_error(error.into());
let _ = sink
.success(resp)
.map_err(|e| warn!("send rpc response"; "err" => %e));
return;
}
let importer = Arc::clone(&self.importer);
let download_speed_limiter = self.download_speed_limiter.clone();
let mem_limit = self.mem_limit;
let tablets = self.tablets.clone();
let start = Instant::now();
let resource_limiter = self.resource_manager.as_ref().and_then(|r| {
r.get_background_resource_limiter(
req.get_context()View on GitHub (pinned to 78aedc1c81)
Solutions
- Populate req.ssts and call batch_download instead
- For a single file, use the single-file fields of the DownloadRequest with the download method
- Fix client code that sets ssts unconditionally regardless of method
Example fix
// before req.set_ssts(vec![meta]); client.download(req).await?; // after: single-file request uses the single-file field req.mut_sst().clone_from(&meta); client.download(req).await?; // or, for multiple files: // client.batch_download(req_with_ssts).await?;
Defensive patterns
Strategy: validation
Validate before calling
if !req.get_ssts().is_empty() {
return Err("use batch_download for multi-file requests");
} Try / catch
let resp = client.download(req).await?;
if let Some(err) = resp.get_error() {
if err.get_message().contains("single-file") {
return client.batch_download(req_for_batch).await.map_err(Into::into);
}
return Err(err.clone().into());
} Prevention
- Branch client code on file count: one file -> download, many -> batch_download
- Never populate ssts when calling the single-file download method
- After migrating to the batch API, update all call sites
- Check DownloadResponse.error and switch endpoints on api-misuse messages
When it happens
Trigger: Invoking the download RPC with req.ssts non-empty (i.e. a DownloadRequest built for the batch API).
Common situations: BR/tooling code migrated to the batch API but still pointing at the download method; codegen or hand-written clients filling both the legacy single-file fields and ssts.
Related errors
- batch_download method only accepts multi-file requests, use
- batch_download_latest_mvcc only accepts multi-file requests
- not implemented
- ttl_seconds must be greater than 0 when task_id is not empty
- you are going to suspend the import RPCs too long. (for {} s
AI-assisted analysis of tikv/tikv@78aedc1c81 (2026-09-03).
Data as JSON: /api/errors/9e64b452f89deffb.
Report an issue: GitHub.