sgl-project/sglang · error · ValueError
Invalid external ngram corpus record at line {line_no}: expe
Error message
Invalid external ngram corpus record at line {line_no}: expected a JSON string. What it means
Each non-blank line of the external ngram corpus must parse to a JSON string (one document per line). If json.loads succeeds but yields a non-str (dict, list, number), this ValueError is raised with the line number.
Source
Thrown at python/sglang/srt/speculative/cpp_ngram/external_corpus.py:39
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 "
f"{line_no}: expected a JSON string."
)
token_ids = list(tokenizer.encode(record, add_special_tokens=False))
if not token_ids:
continue
separator_cost = 1 if has_previous_doc else 0
next_total_tokens = total_tokens + separator_cost + len(token_ids)
if next_total_tokens > max_tokens:
raise ValueError(
"External ngram corpus exceeds the configured token limit "
f"({max_tokens}) at line {line_no} after loading "
f"{total_tokens} tokens."
)
total_tokens = next_total_tokens
View on GitHub (pinned to 0132848349)
Solutions
- Rewrite the corpus to one JSON string per line (json.dumps(doc) for doc in docs)
- Or unwrap the field first: json.dumps(json.loads(line)["text"])
Example fix
# before
{"text": "hello world"}
# after
"hello world" Defensive patterns
Strategy: validation
Validate before calling
import json
def is_string_jsonl(path):
with open(path) as f:
return all(not line.strip() or isinstance(json.loads(line), str) for line in f)
assert is_string_jsonl(path) Type guard
def is_corpus_record(line: str) -> bool:
try:
return isinstance(json.loads(line), str)
except json.JSONDecodeError:
return False Prevention
- Document the one-JSON-string-per-line format next to corpus tools
- Add a schema smoke test for generated corpus files
When it happens
Trigger: A corpus file where lines are JSON objects like {"text": "..."} or JSON arrays instead of plain JSON-encoded strings.
Common situations: Corpus exported in a records format (JSONL with objects) rather than one JSON string per line; mixing token-array corpora with text corpora.
Related errors
- Invalid JSON in external ngram corpus at line {line_no}: {e.
- batching config rule from {source} must be an object, got {t
- Assistant tool call function.arguments must be valid JSON.
- Assistant tool call function.arguments must be a JSON object
- --default-chat-template-kwargs must decode to a JSON object
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/00ec3c696c45f1a1.
Report an issue: GitHub.