sgl-project/sglang · error · ValueError

External ngram corpus max tokens must be positive.

Error message

External ngram corpus max tokens must be positive.

What it means

The external ngram corpus loader enforces a positive token budget: max_tokens must be > 0 because it bounds how many tokens can be inserted into the ngram matcher's global budget. A zero or negative value fails fast with this ValueError.

Source

Thrown at python/sglang/srt/speculative/cpp_ngram/external_corpus.py:22

# Must match SuffixAutomaton::kSeparatorToken in suffix_automaton.h.
SEPARATOR_TOKEN = -(2**31)

# Default chunk size for streaming tokenized documents into the SAM.
DEFAULT_CHUNK_SIZE = 4096


def iter_external_corpus_chunks(
    path: str, tokenizer, max_tokens: int, chunk_size: int = DEFAULT_CHUNK_SIZE
) -> Iterator[list[int]]:
    """Chunk documents and yield fixed-size token chunks from a JSONL corpus file."""
    corpus_path = Path(path)
    if not corpus_path.is_file():
        raise ValueError(f"External ngram corpus path does not exist: {path}")
    if tokenizer is None:
        raise ValueError("A tokenizer is required to load an external ngram corpus.")
    if max_tokens <= 0:
        raise ValueError("External ngram corpus max tokens must be positive.")

    total_tokens = 0
    has_previous_doc = False
    with corpus_path.open("r", encoding="utf-8") as f:
        for line_no, line in enumerate(f, start=1):
            if not line.strip():
                continue

            try:
                record = json.loads(line)
            except json.JSONDecodeError as e:
                raise ValueError(
                    f"Invalid JSON in external ngram corpus at line {line_no}: {e.msg}"
                ) from e

            if not isinstance(record, str):
                raise ValueError(
                    "Invalid external ngram corpus record at line "

View on GitHub (pinned to 0132848349)

Solutions

  1. Pass a positive max_tokens (e.g. the corpus manager's remaining_token_budget if > 0)
  2. If 0 was meant as unlimited, pick an explicit large limit instead
  3. Check remaining_token_budget() before adding another corpus

Example fix

# before
add_external_corpus(path, tok, max_tokens=0)
# after
budget = corpus_manager.remaining_token_budget()
if budget <= 0:
    corpus_manager.remove_external_corpus("old")
    budget = corpus_manager.remaining_token_budget()
add_external_corpus(path, tok, max_tokens=budget)
Defensive patterns

Strategy: validation

Validate before calling

if max_tokens <= 0:
    raise ValueError("max_tokens must be positive")
add_external_corpus(path, tok, max_tokens=max_tokens)

Prevention

When it happens

Trigger: Calling add_external_corpus / iter_external_corpus_chunks with max_tokens=0 or a negative number, e.g. from an unset config default or a computed budget that underflowed to 0.

Common situations: Remaining-budget arithmetic returning 0 (all budget consumed by earlier corpora) and being forwarded as the new corpus's limit; a CLI/config value of 0 intended to mean 'unlimited'.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/c37add70301e6126. Report an issue: GitHub.