sgl-project/sglang · error · TypeError

text must be str, got {type(text).__name__}

Error message

text must be str, got {type(text).__name__}

What it means

encode_text strictly requires a str and raises TypeError naming the actual type otherwise. The Inkling tokenizer wrapper does no implicit coercion before delegating to the base tokenizer's encode().

Source

Thrown at python/sglang/srt/parser/inkling_tokenizer.py:96

        return INKLING_SPECIAL_TOKEN_NAMES[token]
    except KeyError as exc:
        raise KeyError(f"unknown Inkling special token: {token!r}") from exc


@dataclass(frozen=True)
class InklingTokenizer:
    """Small wrapper around a base text tokenizer plus Inkling framing IDs.

    Plain text is encoded by the base tokenizer, while the minimal chat
    framing tokens are inserted from the fixed overlay map.
    """

    tokenizer: Any
    special_token_ids: Mapping[str, int] | None = None

    def encode_text(self, text: str) -> list[int]:
        if not isinstance(text, str):
            raise TypeError(f"text must be str, got {type(text).__name__}")
        return list(self.tokenizer.encode(text, add_special_tokens=False))

    def encode_special(self, token: str) -> int:
        special = normalize_special_token(token)
        token_ids = self.special_token_ids or INKLING_SPECIAL_TOKEN_IDS
        return int(token_ids[special])

    def decode(self, token_ids: list[int]) -> str:
        return self.tokenizer.decode(token_ids)

View on GitHub (pinned to 0132848349)

Solutions

  1. Coerce or guard before calling: decode bytes, substitute '' for None
  2. Check upstream why the value isn't str — usually an empty multimodal content list
  3. Add an isinstance check in your message-assembly code

Example fix

// before
ids = tok.encode_text(content)  # content may be None
// after
ids = tok.encode_text(content if isinstance(content, str) else "")
Defensive patterns

Strategy: type-guard

Validate before calling

text = content if isinstance(content, str) else (content.decode("utf-8") if isinstance(content, bytes) else "")
ids = tok.encode_text(text)

Type guard

def is_str_text(v: Any) -> TypeGuard[str]:
    return isinstance(v, str)

Try / catch

try:
    ids = tok.encode_text(text)
except TypeError as e:
    raise ValueError(f"non-text content reached tokenizer: {e}") from e

Prevention

When it happens

Trigger: Calling encode_text with bytes, None, or an int — e.g. encode_text(b'hello') or encode_text(None) after a content field was left unset.

Common situations: Content fields that are None when a message has only image parts, bytes read from files/streams, or integers from token IDs mistakenly passed back as text.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


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