sgl-project/sglang · error · std::runtime_error
External corpus '${corpus_id}' already exists. Remove it bef
Error message
External corpus '${corpus_id}' already exists. Remove it before adding a new corpus with the same id. What it means
Corpora are stored per corpus_id in a map; installing a new corpus under an id that already exists is rejected to avoid silently replacing data. The staged automaton stays installed... actually staging was already moved; the throw happens under mutex before emplace.
Source
Thrown at python/sglang/kernels/jit/csrc/ngram_corpus/ngram.cpp:98
if (!staging_sam_) {
throw std::runtime_error("appendExternalCorpusTokens called without startExternalCorpusLoad");
}
staging_sam_->appendTokens(tokens);
}
void Ngram::finishExternalCorpusLoad(const std::string& corpus_id) {
if (!staging_sam_) {
throw std::runtime_error("finishExternalCorpusLoad called without startExternalCorpusLoad");
}
staging_sam_->finalize();
if (staging_sam_->empty()) {
staging_sam_.reset();
throw std::runtime_error("External corpus is empty — no tokens were loaded.");
}
// Only lock briefly to install the completed SAM.
std::unique_lock<std::mutex> lock(mutex_);
if (sams_.find(corpus_id) != sams_.end()) {
throw std::runtime_error(
"External corpus '" + corpus_id + "' already exists. Remove it before adding a new corpus with the same id.");
}
sams_.emplace(corpus_id, std::move(staging_sam_));
}
void Ngram::removeExternalCorpus(const std::string& corpus_id) {
std::unique_lock<std::mutex> lock(mutex_);
sams_.erase(corpus_id);
}
void Ngram::resetStagingSam() {
// staging_sam_ is only accessed from the loading thread — no lock needed.
staging_sam_.reset();
}
void Ngram::clearExternalCorpus() {
std::unique_lock<std::mutex> lock(mutex_);
sams_.clear();View on GitHub (pinned to 0132848349)
Solutions
- Call removeExternalCorpus(corpus_id) before loading the same id again
- Use a unique corpus id per load (e.g. versioned: 'wiki-v2')
- Check hasExternalCorpus(corpus_id)/equivalent API before finishing
Example fix
// before
ngram.startExternalCorpusLoad();
/* append */ ngram.finishExternalCorpusLoad("wiki"); // 'wiki' exists
// after
if (has_corpus("wiki")) ngram.removeExternalCorpus("wiki");
ngram.startExternalCorpusLoad();
/* append */ ngram.finishExternalCorpusLoad("wiki"); Defensive patterns
Strategy: try-catch
Validate before calling
// if an exists-check API is available: if (ngram.hasExternalCorpus(id)) ngram.removeExternalCorpus(id); ngram.finishExternalCorpusLoad(id);
Try / catch
try { ngram.finishExternalCorpusLoad(id); } catch (const std::runtime_error& e) {
if (std::string(e.what()).find("already exists") != std::string::npos) { ngram.removeExternalCorpus(id); /* reload */ }
} Prevention
- Use versioned corpus ids (wiki-v2) on refresh
- Always removeExternalCorpus before reloading the same id
When it happens
Trigger: finishExternalCorpusLoad(corpus_id) where corpus_id already has an entry in sams_ (a previous successful load with the same id).
Common situations: Re-running a corpus load script without removeExternalCorpus first; reloading/refreshing a corpus on a long-lived server; id collisions between datasets.
Related errors
- External ngram corpus exceeds the remaining token budget ({m
- External corpus '{corpus_id}' already exists. Remove it befo
- startExternalCorpusLoad called while another load is in prog
- appendExternalCorpusTokens called without startExternalCorpu
- finishExternalCorpusLoad called without startExternalCorpusL
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/c9d79bb880ab7211.
Report an issue: GitHub.