{"record":{"id":"aba44643c21fb72f","repo":"apache/beam","slug":"skip-retrying-because-type-sstream-or-path-is-unsupported","errorCode":null,"errorMessage":"Skip retrying because type %sstream_or_path is unsupported.","messagePattern":"Skip retrying because type (.+?)stream_or_path is unsupported\\.","errorType":"exception","errorClass":"PermanentException","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/dataflow/internal/apiclient.py","lineNumber":758,"sourceCode":"        self.stage_file(\n            gcs_or_local_path, file_name, stream, mime_type, total_size)\n    elif isinstance(stream_or_path, io.IOBase):\n      stream = stream_or_path\n      try:\n        self.stage_file(\n            gcs_or_local_path, file_name, stream, mime_type, total_size)\n      except Exception as exn:\n        if stream.seekable():\n          # reset cursor for possible retrying\n          stream.seek(0)\n          raise exn\n        else:\n          raise retry.PermanentException(\n              \"Skip retrying because we caught exception:\" +\n              ''.join(traceback.format_exception_only(exn.__class__, exn)) +\n              ', but the stream is not seekable.')\n    else:\n      raise retry.PermanentException(\n          \"Skip retrying because type \" + str(type(stream_or_path)) +\n          \"stream_or_path is unsupported.\")\n\n  @retry.no_retries  # Using no_retries marks this as an integration point.\n  def create_job(self, job: Job):\n    \"\"\"Creates job description. May stage and/or submit for remote execution.\"\"\"\n    self.create_job_description(job)\n\n    # Stage and submit the job when necessary\n    dataflow_job_file = job.options.view_as(DebugOptions).dataflow_job_file\n    template_location = (\n        job.options.view_as(GoogleCloudOptions).template_location)\n\n    if job.options.view_as(DebugOptions).lookup_experiment('upload_graph'):\n      self.stage_file_with_retry(\n          job.options.view_as(GoogleCloudOptions).staging_location,\n          \"dataflow_graph.json\",\n          io.BytesIO(job.json().encode('utf-8')))","sourceCodeStart":740,"sourceCodeEnd":776,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/dataflow/internal/apiclient.py#L740-L776","documentation":"stage_file_with_retry only supports seekable streams and file paths. When stream_or_path is neither (some other type), it immediately raises PermanentException stating the type is unsupported, since retries cannot be managed for it.","triggerScenarios":"Calling stage_file_with_retry with an unsupported object type (not a seekable stream and not a path), e.g. bytes, an iterator, a custom object, or None.","commonSituations":"Refactored code passing downloaded content (bytes) directly instead of writing to a temp file; passing a file object that doesn't implement the stream interface; API changes in calling code.","solutions":["Pass a real file path string instead of in-memory content","Wrap bytes/iterator content in a seekable object (io.BytesIO or a temp file)","Check the supported types for stream_or_path in apiclient.py and convert before calling"],"exampleFix":"// before\nstage_file_with_retry(json_bytes, dest)\n// after\nimport io\nstage_file_with_retry(io.BytesIO(json_bytes), dest)  # or a temp file path","handlingStrategy":"type-guard","validationCode":"if not (isinstance(stream_or_path, str) or (hasattr(stream_or_path, 'seekable') and stream_or_path.seekable())):\n    stream_or_path = io.BytesIO(tobytes(stream_or_path))","typeGuard":"def is_supported_stream_or_path(obj):\n    return isinstance(obj, str) or (hasattr(obj, 'seekable') and obj.seekable())","tryCatchPattern":"try:\n    stage_file_with_retry(stream_or_path, dest)\nexcept retry.PermanentException as ex:\n    logger.error('unsupported staging input: %s', ex)\n    raise","preventionTips":["Only pass paths or seekable streams","Convert bytes to BytesIO or temp files first","Add unit tests for the staging helper with both accepted types"],"tags":["python","gcs","upload","type-mismatch","stream"],"backgroundTag":"incompatible-source-type","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}