sgl-project/sglang · error · ValueError

PEFT adapter_config.json must contain a JSON object

Error message

PEFT adapter_config.json must contain a JSON object

What it means

load_peft_config reads adapter_config.json next to the weights and requires it to be a JSON object (dict). If the file exists but parses to a list, string, number, null, or an empty non-dict value, this ValueError is raised. Note json.load of a totally malformed file would raise JSONDecodeError instead; this specifically covers valid JSON of the wrong shape.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/lora/peft_adapter.py:83

                f"safetensors metadata {key!r} must be a positive integer"
            ) from error
        if not math.isfinite(numeric) or numeric <= 0 or not numeric.is_integer():
            raise ValueError(f"safetensors metadata {key!r} must be a positive integer")
        declared.append((key, int(numeric)))
    values = {value for _, value in declared}
    if len(values) > 1:
        raise ValueError(f"conflicting safetensors LoRA alpha metadata: {declared}")
    return declared[0][1] if declared else None


def load_peft_config(weight_path: str) -> dict[str, Any]:
    path = Path(weight_path).with_name("adapter_config.json")
    config = {}
    if path.is_file():
        with path.open(encoding="utf-8") as file:
            config = json.load(file)
    if not isinstance(config, dict):
        raise ValueError("PEFT adapter_config.json must contain a JSON object")
    metadata_alpha = _load_safetensors_lora_alpha(weight_path)
    config_alpha = get_peft_lora_alpha(config)
    if (
        metadata_alpha is not None
        and config_alpha is not None
        and metadata_alpha != config_alpha
    ):
        raise ValueError(
            "adapter_config.json lora_alpha conflicts with safetensors metadata: "
            f"{config_alpha} != {metadata_alpha}"
        )
    if metadata_alpha is not None:
        config.setdefault("lora_alpha", metadata_alpha)
    return config


def get_peft_lora_alpha(config: Mapping[str, Any]) -> int | None:
    alpha = config.get("lora_alpha")

View on GitHub (pinned to 0132848349)

Solutions

  1. Validate adapter_config.json parses to an object: python -c "import json;print(type(json.load(open('adapter_config.json'))))"
  2. Fix the file to be a flat JSON object of PEFT config keys (peft_type, lora_alpha, r, target_modules, ...)
  3. Ensure weight_path points at the actual adapter directory

Example fix

// before: adapter_config.json contains [ {"lora_alpha": 16} ]
// after:  adapter_config.json contains { "lora_alpha": 16, "peft_type": "LORA", "r": 16 }
Defensive patterns

Strategy: validation

Validate before calling

import json
cfg = json.load(open(p / "adapter_config.json"))
assert isinstance(cfg, dict), "adapter_config.json must be a JSON object"

Type guard

def is_peft_config_object(cfg) -> bool:
    return isinstance(cfg, dict)

Try / catch

try:
    cfg = load_peft_config(path)
except ValueError as e:
    if "must contain a JSON object" in str(e):
        cfg = json.load(open(path / "adapter_config.json"))
        if not isinstance(cfg, dict):
            raise  # genuinely malformed, fix the file
    raise

Prevention

When it happens

Trigger: Placing an adapter_config.json that contains a JSON array or scalar string next to the LoRA weights, then calling load_lora_adapter / load_peft_config on that path.

Common situations: Hand-written config files, config generators that emit wrapped arrays, or accidentally pointing weight_path at a directory containing an unrelated adapter_config.json.

Related errors


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