sgl-project/sglang · error · ValueError

config not published; cannot read a config leaf

Error message

config not published; cannot read a config leaf

What it means

Thrown by RuntimeContext.config_leaf when a caller tries to read a config leaf before any publish(server_args, role=...) has happened. The config bags (namespaced projections of ServerArgs) only exist after publish, so there is nothing to read from. The runtime deliberately fails fast instead of returning stale or default values.

Source

Thrown at python/sglang/srt/runtime_context.py:933

                        f"override: subgroup {seg!r} missing under {path!r}"
                    )
            if name not in bag:
                raise ValueError(f"override: field {name!r} not projected on {path!r}")
            targets.append((bag, name, value))
        for bag, name, value in targets:
            bag._set(name, value)
        self._overrides_log.append((source, dict(fields)))

    def config_leaf(self, name: str):
        """One resolved config leaf by field name — the read side of ``override``.

        Callers that hold a field name rather than a namespace (a readback
        endpoint, a control-plane handler) would otherwise have to know which
        bag it lives in.
        """
        bags = self._config_bags
        if bags is None:
            raise ValueError("config not published; cannot read a config leaf")
        from sglang.srt.arg_groups.arg_utils import namespace_of

        path = namespace_of(type(self._server_args)).get(name)
        if path is None:
            raise ValueError(f"{name!r} is not a config leaf (no NS namespace)")
        parts = path.split(".")
        bag = self.config_bag(parts[0])
        for seg in parts[1:]:
            bag = object.__getattribute__(bag, "_subs").get(seg)
            if bag is None:
                raise ValueError(f"subgroup {seg!r} missing under {path!r}")
        return getattr(bag, name)

    def overrides_log(self) -> list:
        """Provenance of post-publish ``override`` calls: ``[(source, {field: value})]``.

        Returns deep-ish copies (source, dict(fields)) so callers inspecting the
        log cannot mutate the recorded provenance in place."""

View on GitHub (pinned to 0132848349)

Solutions

  1. Move the config_leaf/config_value read out of constructors into code that runs after the process entry publishes (add publish(server_args, role=...) at the entry point)
  2. In tests, publish a minimal ServerArgs via runtime_context.publish(...) in setUp before constructing components
  3. Guard the read on whether config bags exist and defer it until publish has run

Example fix

# before
def __init__(self):
    self.value = ctx.config_leaf("some_field")
# after
def start(self):  # runs after publish(server_args, role=...)
    self.value = ctx.config_leaf("some_field")
Defensive patterns

Strategy: validation

Validate before calling

from sglang.srt.runtime_context import _CONTEXT
if _CONTEXT._config_bags is None:
    raise RuntimeError("publish server_args before reading config leaves")
value = _CONTEXT.config_leaf(name)

Prevention

When it happens

Trigger: Calling ctx.config_leaf(name) or ctx.config_value(name) (e.g. from a readback endpoint or control-plane handler) before the process entry point ran runtime_context.publish(server_args, role=...). Typical when a constructor or module-import-time code reads a config leaf.

Common situations: Refactoring code that used to read ServerArgs directly into the config-leaf API and calling it during __init__ instead of after publish; unit tests that construct components without publishing a context first.

Related errors


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