[ISSUE] `get_api_error` fails with `TypeError: object of type '_io.BufferedReader' has no len()¨`

オープン 初心者向け
#1,489 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@mittalpk がすでに取り組んでいます。

2026年7月24日 から。

  • #1497 @mittalpk による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
静か
技術スタック
python

調査の方向性

databricks/sdk/logger/round_trip_logger.py の _redacted_dump から始め、databricks/sdk/errors/parser.py からの呼び出しを追跡します。body がローカルファイルのストリームである PUT リクエストの API エラーを再現し、その後、エラーパーサーとロガーが TypeError を発生させずに BufferedReader を処理できることを確認します。

索引モデルが issue の本文から書いたものです。

説明

Description

When the HTTP PUT request body is streamed from a local file, request.body is not a string but a _io.BufferedReader.

In case of API error, _BaseClient._error_parser.get_api_error(response) will try to return the error and the associated query.

https://github.com/databricks/databricks-sdk-py/blob/be7acc03728c5adf571f60d49ace4fd707d48f8b/databricks/sdk/errors/parser.py#L93-L96

Unfortunately, response.request.body is still a BufferedReader, not necessarily a string. When this body is passed to the logger, it fails

https://github.com/databricks/databricks-sdk-py/blob/be7acc03728c5adf571f60d49ace4fd707d48f8b/databricks/sdk/logger/round_trip_logger.py#L46-L47

eventually calls self._redacted_dump("> ", request.body) but the latter is not meant to handle streams

Full strack trace :

Traceback (most recent call last):
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\generic.py", line 350, in transfer
    _try_links(
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\generic.py", line 281, in _try_links
    return copy(
           ^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\generic.py", line 88, in copy
    return _put(
           ^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\generic.py", line 161, in _put
    _put_one(from_paths[0], to_paths[0])
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\generic.py", line 151, in _put_one
    return to_fs.put_file(
           ^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_objects\fs\base.py", line 673, in put_file
    self.fs.put_file(os.fspath(from_file), to_info, callback=callback, **kwargs)
  File "C:\_dev\my_proj\.venv\Lib\site-packages\dvc_databricks\filesystem.py", line 308, in put_file
    self._client.files.upload(rpath, fh, overwrite=True)
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\mixins\files.py", line 1430, in upload
    self._upload_single_thread_with_known_size(ctx, contents)
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\mixins\files.py", line 1513, in _upload_single_thread_with_known_size
    return self._single_thread_single_shot_upload(ctx, contents)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\mixins\files.py", line 1521, in _single_thread_single_shot_upload
    return super().upload(file_path=ctx.target_path, contents=contents, overwrite=ctx.overwrite)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\service\files.py", line 1027, in upload
    self._api.do(
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\core.py", line 95, in do
    return self._api_client.do(
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\_base_client.py", line 197, in do
    response = call(
               ^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\retries.py", line 59, in wrapper
    raise err
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\retries.py", line 38, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\_base_client.py", line 297, in _perform
    error = self._error_parser.get_api_error(response)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\errors\parser.py", line 95, in get_api_error
    {"message": "unable to parse response. " + _unknown_error(response, self._debug_headers)},
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\errors\parser.py", line 45, in _unknown_error
    request_log = RoundTrip(response, debug_headers=debug_headers, debug_truncate_bytes=10 * 1024).generate()
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\logger\round_trip_logger.py", line 47, in generate
    sb.append("> [raw stream]" if self._raw else self._redacted_dump("> ", request.body))
                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\_dev\my_proj\.venv\Lib\site-packages\databricks\sdk\logger\round_trip_logger.py", line 113, in _redacted_dump
    if len(body) == 0:
       ^^^^^^^^^
TypeError: object of type '_io.BufferedReader' has no len()

A suggested fix could be :

    def _redacted_dump(self, prefix: str, body: str) -> str:
        if isinstance(body, io.IOBase):
            # Read the stream into a string-like
            body.seek(0)
            body = body.read().decode("utf-8")
        
        if len(body) == 0:
            return ""
主要言語
Python
スター
577
フォーク
229
平均マージ
40分
マージ済み PR(30日)
12

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

databricks/databricks-sdk-py のほかの issue

databricks/databricks-sdk-py の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。