tatsu-lab/stanford_alpaca · error · ValueError

Unexpected type: {type(obj)}

Error message

Unexpected type: {type(obj)}

What it means

This error is raised by jdump() in alpaca-lora's utils.py when the object passed to it is neither a dict/list (JSON-serializable structure) nor a str. The function only supports three types: dict and list are serialized with json.dump, str is written verbatim, and anything else triggers this ValueError. It exists to fail fast on unsupported payloads rather than silently writing garbage.

Source

Thrown at utils.py:164


def jdump(obj, f, mode="w", indent=4, default=str):
    """Dump a str or dictionary to a file in json format.

    Args:
        obj: An object to be written.
        f: A string path to the location on disk.
        mode: Mode for opening the file.
        indent: Indent for storing json dictionaries.
        default: A function to handle non-serializable entries; defaults to `str`.
    """
    f = _make_w_io_base(f, mode)
    if isinstance(obj, (dict, list)):
        json.dump(obj, f, indent=indent, default=default)
    elif isinstance(obj, str):
        f.write(obj)
    else:
        raise ValueError(f"Unexpected type: {type(obj)}")
    f.close()


def jload(f, mode="r"):
    """Load a .json file into a dictionary."""
    f = _make_r_io_base(f, mode)
    jdict = json.load(f)
    f.close()
    return jdict

View on GitHub (pinned to 761dc5bfbd)

Solutions

  1. Ensure the value passed to jdump is a plain list or dict, e.g. convert with list(...) before dumping
  2. If the object is a datasets.Dataset or iterable of dicts, materialize it: data = [ex for ex in dataset] or list(dataset)
  3. If it's a string you intended to write, pass the str itself, not a wrapped object
  4. If you genuinely need other container types (e.g. tuple), extend jdump's isinstance check — e.g. add tuple and convert to list before json.dump

Example fix

# before
jdump(dataset.map(format_fn), 'data.json')  # Dataset object -> ValueError

# after
formatted = [format_fn(ex) for ex in dataset]
jdump(formatted, 'data.json')
Defensive patterns

Strategy: type-guard

Validate before calling

import json

def is_jdump_safe(obj):
    return isinstance(obj, (dict, list, str))

if not is_jdump_safe(data):
    data = list(data)  # or raise/convert appropriately
jdump(data, 'out.json')

Type guard

def is_jdump_payload(obj) -> bool:
    """jdump only accepts dict, list, or str."""
    return isinstance(obj, (dict, list, str))

Try / catch

try:
    jdump(data, out_path)
except ValueError as e:
    if 'Unexpected type' in str(e):
        data = list(data)  # materialize iterables/generators
        jdump(data, out_path)
    else:
        raise

Prevention

When it happens

Trigger: Calling generate_instruction_following_data() (or jdump directly) with a data object that is not a dict or list — e.g. a generator, tuple, numpy array, or a datasets.Dataset object. Also happens when refactoring produces data as an iterable that is never materialized into a list before dumping.

Common situations: Converting the generate instruction-following data script to stream from HuggingFace datasets (dataset.map returns a Dataset, not a list); returning a generator expression from generate_prompt_instruction_tuples; tuples returned instead of lists after code changes; numpy types leaking into the top-level object.


AI-assisted analysis of tatsu-lab/stanford_alpaca@761dc5bfbd (2026-08-28). Data as JSON: /api/errors/a955ef4a25e85b1d. Report an issue: GitHub.