{"record":{"id":"ae6bd63808af752a","repo":"sgl-project/sglang","slug":"config-not-published-cannot-read-a-config-leaf","errorCode":null,"errorMessage":"config not published; cannot read a config leaf","messagePattern":"config not published; cannot read a config leaf","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/runtime_context.py","lineNumber":933,"sourceCode":"                        f\"override: subgroup {seg!r} missing under {path!r}\"\n                    )\n            if name not in bag:\n                raise ValueError(f\"override: field {name!r} not projected on {path!r}\")\n            targets.append((bag, name, value))\n        for bag, name, value in targets:\n            bag._set(name, value)\n        self._overrides_log.append((source, dict(fields)))\n\n    def config_leaf(self, name: str):\n        \"\"\"One resolved config leaf by field name — the read side of ``override``.\n\n        Callers that hold a field name rather than a namespace (a readback\n        endpoint, a control-plane handler) would otherwise have to know which\n        bag it lives in.\n        \"\"\"\n        bags = self._config_bags\n        if bags is None:\n            raise ValueError(\"config not published; cannot read a config leaf\")\n        from sglang.srt.arg_groups.arg_utils import namespace_of\n\n        path = namespace_of(type(self._server_args)).get(name)\n        if path is None:\n            raise ValueError(f\"{name!r} is not a config leaf (no NS namespace)\")\n        parts = path.split(\".\")\n        bag = self.config_bag(parts[0])\n        for seg in parts[1:]:\n            bag = object.__getattribute__(bag, \"_subs\").get(seg)\n            if bag is None:\n                raise ValueError(f\"subgroup {seg!r} missing under {path!r}\")\n        return getattr(bag, name)\n\n    def overrides_log(self) -> list:\n        \"\"\"Provenance of post-publish ``override`` calls: ``[(source, {field: value})]``.\n\n        Returns deep-ish copies (source, dict(fields)) so callers inspecting the\n        log cannot mutate the recorded provenance in place.\"\"\"","sourceCodeStart":915,"sourceCodeEnd":951,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/runtime_context.py#L915-L951","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","In tests, publish a minimal ServerArgs via runtime_context.publish(...) in setUp before constructing components","Guard the read on whether config bags exist and defer it until publish has run"],"exampleFix":"# before\ndef __init__(self):\n    self.value = ctx.config_leaf(\"some_field\")\n# after\ndef start(self):  # runs after publish(server_args, role=...)\n    self.value = ctx.config_leaf(\"some_field\")","handlingStrategy":"validation","validationCode":"from sglang.srt.runtime_context import _CONTEXT\nif _CONTEXT._config_bags is None:\n    raise RuntimeError(\"publish server_args before reading config leaves\")\nvalue = _CONTEXT.config_leaf(name)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call publish(server_args, role=...) at the process entry point before any component reads config","Avoid reading config leaves in constructors; defer reads to start()/run() methods","In tests, publish a minimal ServerArgs in setUp"],"tags":["config","runtime-context","initialization-order","sglang"],"backgroundTag":"config-not-initialized","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}