Issues in OSDK? pydantic.ValidationError when using timeseries_property.to_pandas() in Python Functions

Language : Python
Generator Version : 2.107.0

Hi,

I’m writing a Python function that deals with the TimeSeries property of an Ontology object. I’ve confirmed that the generated OSDK properly maps a TimeSeries class to the object property, and I followed the documentation to calculate the mean value.

However, I ran into the following exception:

Example function:

@function
def timeseries_example_function(machinePart: Part, start: datetime, end: datetime) -> float:
    df = machinePart.timeseries_property.to_pandas(start=start, end=end) # -> causes exception
    return df["value"].mean()

Logs:

...
File "/scratch/standalone/ /code-assist/contents/python-functions/python/python_functions/my_function.py", line 16, in timeseires_example_function
    df = machinePart.timeseries_property.to_pandas(start=start, end=end)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/scratch/standalone/ /code-assist/contents/python-functions/build/conda/test-env/lib/python3.12/site-packages/foundry_sdk_runtime/timeseries/timeseries.py", line 140, in to_pandas
    stream_reader = query.arrow_stream()
                    ^^^^^^^^^^^^^^^^^^^^
  File "/scratch/standalone/ /code-assist/contents/python-functions/build/conda/test-env/lib/python3.12/site-packages/foundry_sdk_runtime/timeseries/timeseries_query.py", line 42, in arrow_stream
    stream = self._ontologies_client.TimeSeriesPropertyV2.stream_points(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/scratch/standalone/ /code-assist/contents/python-functions/build/conda/test-env/lib/python3.12/site-packages/foundry_sdk/_core/utils.py", line 96, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/scratch/standalone/ /code-assist/contents/python-functions/build/conda/test-env/lib/python3.12/site-packages/pydantic/_internal/_validate_call.py", line 39, in wrapper_function
    return wrapper(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/scratch/standalone/ /code-assist/contents/python-functions/build/conda/test-env/lib/python3.12/site-packages/pydantic/_internal/_validate_call.py", line 136, in __call__
    res = self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValidationError: 1 validation error for TimeSeriesPropertyV2Client.stream_points
range
  Unable to extract tag using discriminator 'type' [type=union_tag_not_found, input_value={'range': {'type': 'absol...'}}, input_type=dict]

My Investigation & Suspected Cause

I’ve traced the call stack and analyzed the SDK code. The issue seems to be a mismatch between the object created by TimeseriesQuery and the object expected by the TimeSeriesPropertyV2.stream_points API.

1. Call chain

The .to_pandas() method calls TimeseriesQuery.arrow_stream(), which in leads to calling the TimeSeriesPropertyV2.stream_points API endpoint.

foundry_sdk_runtime/timeseries/timeseries_query.py :

# The arrow_stream method in TimeseriesQuery calls the low-level API
stream = self._ontologies_client.TimeSeriesPropertyV2.stream_points(
    ontology=self._ontology_rid,
    object_type=self._object_type,
    primary_key=str(self._object_primary_key),
    property=self._property_name,
    format="ARROW",
    range=self._time_range,  # <--- This is the argument causing the issue
)

2. API’s expectation

The stream_points method uses a Pydantic model that expects a TimeRange object. This model is a discriminated union identified by the type field.

TimeRange = typing_extensions.Annotated[
    typing.Union[AbsoluteTimeRange, RelativeTimeRange], pydantic.Field(discriminator="type")
]

# The API signature expecting the model
def stream_points(
    self,
    ...
    range: typing.Optional[ontologies_models.TimeRange] = None,
    ...
) -> bytes:
    pass

Therefore, the expected JSON structure for the range argument would be like below.

{
  "type": "absolute",
  "startTime": "2025-08-30T15:00:00Z",
  "endTime": "2025-08-30T16:00:00Z"
}

3. TimeseriesQuery

The TimeseriesQuery class incorrectly wraps the TimeRange object inside another dictionary with a "range" key.

# foundry_sdk_runtime/timeseries/types.py :
class RelativeTimeRange(AliasedBaseModel):
    type: Literal["relative"] = "relative"
    startTime: Optional[RelativeTime]
    endTime: Optional[RelativeTime]

class AbsoluteTimeRange(AliasedBaseModel):
    type: Literal["absolute"] = "absolute"
    startTime: Optional[datetime]
    endTime: Optional[datetime]


class TimeRange(AliasedBaseModel):
    range: Union[AbsoluteTimeRange, RelativeTimeRange]

# foundry_sdk_runtime/timeseries/timeseries_query.py :
class TimeseriesQuery(Generic[T]):
    def __init__(
        self,
        # ...
        time_range: Optional[TimeRange] = None,
    ):
        # ...
        self._time_range = json.loads(time_range.model_dump_json()) if time_range is not None else {}

As a result, the actual object being passed to the range parameter would be :

{
  "range": {
    "type": "absolute",
    "startTime": "2025-08-30T15:00:00Z",
    "endTime": "2025-08-30T16:00:00Z"
  }
}

I believe this causes the fail of Pydantic validation, which is looking for the type field at the top level.

Also, although I can’t debug the SDK directly, I could find the relevant exception log.
related line)

Unable to extract tag using discriminator 'type' [type=union_tag_not_found, input_value={'range': {'type': 'absol...8-28T16:50:31.726000Z'}}, input_type=dict]

Since I cannot debug or modify the SDK directly, my current workaround is using Typescript function.

Has anyone else encountered this issue? Is there a Python-side workaround to properly unwrap or pass the range so .to_pandas() works without validation errors?

Thanks in advance!

1 Like

Hi @JaesungPark thank you for flagging the issue and for the thorough investigation. We’ve confirmed the bug in Python OSDK and released a fix in version 2.109.0. Please let us know if you run into additional issues with the time series queries on Python OSDK.

1 Like