huggingface/smolagents · error · ValueError

The model output does not contain any JSON blob.

Error message

The model output does not contain any JSON blob.

What it means

parse_json_blob extracts the substring between the first '{' and the last '}' of model output and json.loads it. If no '{' or '}' exists, indexing/slicing raises IndexError, which is converted to this ValueError: the model produced no JSON at all.

Source

Thrown at src/smolagents/utils.py:175

        return {str(k): make_json_serializable(v) for k, v in obj.items()}
    elif hasattr(obj, "__dict__"):
        # For custom objects, convert their __dict__ to a serializable format
        return {"_type": obj.__class__.__name__, **{k: make_json_serializable(v) for k, v in obj.__dict__.items()}}
    else:
        # For any other type, convert to string
        return str(obj)


def parse_json_blob(json_blob: str) -> tuple[dict[str, str], str]:
    "Extracts the JSON blob from the input and returns the JSON data and the rest of the input."
    try:
        first_accolade_index = json_blob.find("{")
        last_accolade_index = [a.start() for a in list(re.finditer("}", json_blob))][-1]
        json_str = json_blob[first_accolade_index : last_accolade_index + 1]
        json_data = json.loads(json_str, strict=False)
        return json_data, json_blob[:first_accolade_index]
    except IndexError:
        raise ValueError("The model output does not contain any JSON blob.")
    except json.JSONDecodeError as e:
        place = e.pos
        if json_blob[place - 1 : place + 2] == "},\n":
            raise ValueError(
                "JSON is invalid: you probably tried to provide multiple tool calls in one action. PROVIDE ONLY ONE TOOL CALL."
            )
        raise ValueError(
            f"The JSON blob you used is invalid due to the following error: {e}.\n"
            f"JSON blob was: {json_blob}, decoding failed on that specific part of the blob:\n"
            f"'{json_blob[place - 4 : place + 5]}'."
        )


def extract_code_from_text(text: str, code_block_tags: tuple[str, str]) -> str | None:
    """Extract code from the LLM's output."""
    pattern = rf"{code_block_tags[0]}(.*?){code_block_tags[1]}"
    matches = re.findall(pattern, text, re.DOTALL)
    if matches:

View on GitHub (pinned to 30bb116109)

Solutions

  1. Retry the step so the model regenerates a proper JSON action
  2. Use a stronger model or one of the built-in prompt templates suited to the model
  3. Increase max_tokens / fix truncation so full JSON is emitted
  4. Wrap agent.run steps with error handling and feed the error back as an observation so the agent self-corrects

Example fix

# before
action = '{"name": "search", ...'  # truncated by max_tokens

# after
model = OpenAIServerModel(model_id='...', max_tokens=2000)
agent.run(task)
Defensive patterns

Strategy: retry

Validate before calling

def has_json_blob(text: str) -> bool:
    return '{' in text and '}' in text

Type guard

def looks_like_action(text: str) -> bool:
    import re
    return bool(re.search(r'\{.*\}', text, re.DOTALL))

Try / catch

try:
    data, pre = parse_json_blob(text)
except ValueError as e:
    if 'does not contain any JSON blob' in str(e):
        # feed error back as observation and re-run the model step
        raise

Prevention

When it happens

Trigger: A ToolCallingAgent model reply containing only prose/thoughts with no JSON object; get_tool_call_from_text receiving chatty output without braces; empty or whitespace model responses.

Common situations: Weak or misconfigured chat models that ignore the tool-calling JSON format; truncated responses from timeouts or max-token limits; wrong prompt template for the model type.

Related errors


AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28). Data as JSON: /api/errors/2b2b22097d23d40c. Report an issue: GitHub.