openai/openai-python · error · RuntimeError

Could not convert data into a valid instance of {type_}

Error message

Could not convert data into a valid instance of {type_}

What it means

construct_type() failed to coerce the incoming data into the annotated type. For Union types, every variant was attempted and each raised, so the data matches none of the allowed shapes and a RuntimeError summarizing the failure is raised.

Source

Thrown at src/openai/_models.py:654

        #
        # without this block, if the data we get is something like `{'kind': 'bar', 'value': 'foo'}` then
        # we'd end up constructing `FooType` when it should be `BarType`.
        discriminator = _build_discriminated_union_meta(union=type_, meta_annotations=meta)
        if discriminator and is_mapping(value):
            variant_value = value.get(discriminator.field_alias_from or discriminator.field_name)
            if variant_value and isinstance(variant_value, str):
                variant_type = discriminator.mapping.get(variant_value)
                if variant_type:
                    return construct_type(type_=variant_type, value=value)

        # if the data is not valid, use the first variant that doesn't fail while deserializing
        for variant in args:
            try:
                return construct_type(value=value, type_=variant)
            except Exception:
                continue

        raise RuntimeError(f"Could not convert data into a valid instance of {type_}")

    if origin == dict:
        if not is_mapping(value):
            return value

        _, items_type = get_args(type_)  # Dict[_, items_type]
        return {key: construct_type(value=item, type_=items_type) for key, item in value.items()}

    if (
        not is_literal_type(type_)
        and inspect.isclass(origin)
        and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel))
    ):
        if is_list(value):
            return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value]

        if is_mapping(value):
            if issubclass(type_, BaseModel):

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Log/inspect the raw value being converted and compare it against the model's expected fields
  2. Upgrade the openai package to the latest version so response models match the current API schema
  3. If building manually, pass the exact field names and types the model declares, or use construct()/build for non-validated construction

Example fix

// before
construct_type(value={"finshed": True}, type_=CompletionUsage)
// after
construct_type(value={"finished": True}, type_=CompletionUsage)
Defensive patterns

Strategy: try-catch

Validate before calling

if not isinstance(data, Mapping):
    data = coerce_or_reject(data)

Type guard

def matches_model_shape(data: object, model: type[BaseModel]) -> bool:
    return isinstance(data, Mapping) and all(k in model.model_fields for k in data)

Try / catch

try:
    obj = construct_type(value=data, type_=MyUnion)
except RuntimeError as e:
    if 'Could not convert data' in str(e):
        logger.error('unexpected payload shape: %r', data)
    raise

Prevention

When it happens

Trigger: A response body or nested field doesn't match any variant of a Union type (e.g. expecting str or ChatCompletion but receiving an error object), or a manually constructed value passed to construct/build with mismatched keys/types.

Common situations: API returns an unexpected payload shape (error envelope, new field type) on an older SDK version; hand-building model instances with typo'd field names; partial data passed to construct_type.

Related errors


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/f36ee9ba61c68238. Report an issue: GitHub.