chroma-core/chroma · error · ValueError

Unable to decode configuration from JSON string: {json_str}

Error message

Unable to decode configuration from JSON string: {json_str}

What it means

ConfigurationInternal.from_json_str (chromadb/api/configuration.py:185) raises this ValueError when json.loads fails on the input string. It is a plain decode failure before any configuration logic runs: the string is not valid JSON (truncated, empty, BOM or encoding issues, single quotes, trailing commas). The original JSONDecodeError is swallowed and re-raised with the offending string embedded in the message.

Source

Thrown at chromadb/api/configuration.py:185

        if definition.is_static:
            raise StaticParameterError(f"Cannot set static parameter: {name}")
        if not definition.validator(value):
            raise ValueError(f"Invalid value for parameter {name}: {value}")
        parameter.value = value

    @override
    def to_json_str(self) -> str:
        """Returns the JSON representation of the configuration."""
        return json.dumps(self.to_json())

    @classmethod
    @override
    def from_json_str(cls, json_str: str) -> Self:
        """Returns a configuration from the given JSON string."""
        try:
            config_json = json.loads(json_str)
        except json.JSONDecodeError:
            raise ValueError(
                f"Unable to decode configuration from JSON string: {json_str}"
            )
        return cls.from_json(config_json) if config_json else cls()

    @override
    def to_json(self) -> Dict[str, Any]:
        """Returns the JSON compatible dictionary representation of the configuration."""
        json_dict = {
            name: parameter.value.to_json()
            if isinstance(parameter.value, ConfigurationInternal)
            else parameter.value
            for name, parameter in self.parameter_map.items()
        }
        # What kind of configuration is this?
        json_dict["_type"] = self.__class__.__name__
        return json_dict

    @classmethod

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Parse-then-pass: call json.loads yourself in a try/except json.JSONDecodeError to get line/column diagnostics, fix the payload, then hand the parsed dict to from_json
  2. If you must use from_json_str, wrap it and catch ValueError; log the string length and first bytes to find truncation
  3. Produce the string only via to_json_str()/json.dumps so it is guaranteed well-formed

Example fix

# before
cfg = HNSWConfigurationInternal.from_json_str(raw)   # raw is truncated/invalid
# after
import json
try:
    parsed = json.loads(raw)
except json.JSONDecodeError as e:
    raise ValueError(f"bad config JSON at line {e.lineno} col {e.colno}") from e
cfg = HNSWConfigurationInternal.from_json(parsed) if parsed else HNSWConfigurationInternal()
Defensive patterns

Strategy: try-catch

Validate before calling

import json

def parse_config_str(raw: str):
    try:
        return json.loads(raw)
    except json.JSONDecodeError as e:
        raise ValueError(f"malformed config JSON: {e.msg} at line {e.lineno}") from e

Try / catch

import json

try:
    cfg = Cls.from_json_str(raw)
except ValueError as e:
    if "Unable to decode" in str(e):
        parsed = json.loads(raw.strip().lstrip("\ufeff"))  # fix BOM/whitespace
        cfg = Cls.from_json(parsed) if parsed else Cls()
    else:
        raise

Prevention

When it happens

Trigger: Passing a truncated or empty string, a file read in binary mode (bytes with BOM), Python-repr dicts (single quotes) instead of JSON, or strings assembled by concatenation with a trailing comma.

Common situations: Config strings stored in env vars or databases getting clipped; writing dicts with str(dict) instead of json.dumps; encoding mismatches after file transfers (BOM, latin-1 bytes).

Understand the failure class

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/967792b7d13f9a21. Report an issue: GitHub.