apache/beam · error · PermanentException

Skip retrying because type %sstream_or_path is unsupported.

Error message

Skip retrying because type %sstream_or_path is unsupported.

What it means

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.

Solutions

  1. Pass a real file path string instead of in-memory content
  2. Wrap bytes/iterator content in a seekable object (io.BytesIO or a temp file)
  3. Check the supported types for stream_or_path in apiclient.py and convert before calling

Example fix

// before
stage_file_with_retry(json_bytes, dest)
// after
import io
stage_file_with_retry(io.BytesIO(json_bytes), dest)  # or a temp file path
Defensive patterns

Strategy: type-guard

Validate before calling

if not (isinstance(stream_or_path, str) or (hasattr(stream_or_path, 'seekable') and stream_or_path.seekable())):
    stream_or_path = io.BytesIO(tobytes(stream_or_path))

Type guard

def is_supported_stream_or_path(obj):
    return isinstance(obj, str) or (hasattr(obj, 'seekable') and obj.seekable())

Try / catch

try:
    stage_file_with_retry(stream_or_path, dest)
except retry.PermanentException as ex:
    logger.error('unsupported staging input: %s', ex)
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/aba44643c21fb72f. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/runners/dataflow/internal/apiclient.py:758

        self.stage_file(
            gcs_or_local_path, file_name, stream, mime_type, total_size)
    elif isinstance(stream_or_path, io.IOBase):
      stream = stream_or_path
      try:
        self.stage_file(
            gcs_or_local_path, file_name, stream, mime_type, total_size)
      except Exception as exn:
        if stream.seekable():
          # reset cursor for possible retrying
          stream.seek(0)
          raise exn
        else:
          raise retry.PermanentException(
              "Skip retrying because we caught exception:" +
              ''.join(traceback.format_exception_only(exn.__class__, exn)) +
              ', but the stream is not seekable.')
    else:
      raise retry.PermanentException(
          "Skip retrying because type " + str(type(stream_or_path)) +
          "stream_or_path is unsupported.")

  @retry.no_retries  # Using no_retries marks this as an integration point.
  def create_job(self, job: Job):
    """Creates job description. May stage and/or submit for remote execution."""
    self.create_job_description(job)

    # Stage and submit the job when necessary
    dataflow_job_file = job.options.view_as(DebugOptions).dataflow_job_file
    template_location = (
        job.options.view_as(GoogleCloudOptions).template_location)

    if job.options.view_as(DebugOptions).lookup_experiment('upload_graph'):
      self.stage_file_with_retry(
          job.options.view_as(GoogleCloudOptions).staging_location,
          "dataflow_graph.json",
          io.BytesIO(job.json().encode('utf-8')))

View on GitHub (pinned to 12126d8942)