sgl-project/sglang · error · ValueError

DFLASH mask_token must be a non-empty string, got

Error message

DFLASH mask_token must be a non-empty string, got {mask_token!r}.

What it means

Thrown during DFLASH worker initialization when the configured mask_token is not a non-empty string. DFLASH drafts rely on a mask token to represent masked positions; the worker validates it before resolving its token id against the target vocab. Passing None, an int, or '' fails here with the offending value echoed.

Solutions

  1. Set the mask token as its string form, e.g. --speculative-dflash-mask-token "<mask>" (or the model's documented mask token string)
  2. If you only know the id, find the token string via tokenizer.decode([id]) and pass that string
  3. Remove empty-string overrides so the model's default mask token applies

Example fix

# before
--speculative-algorithm DFLASH \
--speculative-dflash-mask-token ""

# after
--speculative-algorithm DFLASH \
--speculative-dflash-mask-token "<|mask|>"
Defensive patterns

Strategy: validation

Validate before calling

mask_token = server_args.speculative_dflash_mask_token
assert isinstance(mask_token, str) and mask_token, (
    f"mask_token must be a non-empty string, got {mask_token!r}"
)

Type guard

def is_valid_mask_token(v) -> bool:
    return isinstance(v, str) and len(v) > 0

Prevention

When it happens

Trigger: Server/speculative config where speculative_dflash_mask_token is omitted from the config class default and ends up None, set to an integer id by mistake, or set to the empty string in a launch script/JSON config.

Common situations: Hand-written launch scripts or overrides that set the mask token to an id (e.g. 128000) instead of the string form; config migration dropping the field; YAML/JSON quoting mistakes producing non-string values.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at python/sglang/srt/speculative/dflash_worker_v2.py:876

            )

            assert self._draft_block_end_buf is not None
            block_end = self._draft_block_end_buf[:bs]
            torch.add(draft_prefix_lens, block_size, out=block_end)
            assign_req_to_token_pool_func(
                req_pool_indices,
                self.draft_model_runner.req_to_token_pool.req_to_token,
                draft_prefix_lens,
                block_end,
                verify_out_cache_loc_2d.reshape(-1),
                bs,
            )

    def _resolve_mask_token_id(
        self, *, mask_token: str, mask_token_id: Optional[int] = None
    ) -> int:
        if not isinstance(mask_token, str) or not mask_token:
            raise ValueError(
                f"DFLASH mask_token must be a non-empty string, got {mask_token!r}."
            )

        vocab_size = int(self.target_worker.model_runner.model_config.vocab_size)
        if mask_token_id is not None:
            resolved_id = int(mask_token_id)
            if resolved_id >= vocab_size:
                raise ValueError(
                    "DFLASH mask_token_id is outside the target vocab size. "
                    f"mask_token_id={resolved_id}, vocab_size={vocab_size}. "
                    f"This likely means mask_token={mask_token!r} requires vocab expansion beyond the model's embedding size. "
                    "SGLang does not support resizing target embeddings for DFLASH yet."
                )

            tokenizer = getattr(self.target_worker, "tokenizer", None)
            if tokenizer is not None:
                token_id_from_vocab = tokenizer.get_vocab().get(mask_token, None)
                if (

View on GitHub (pinned to 0132848349)