apache/beam · error · IOError

ENOENT

ENOENT

Error message

Not found: %s

What it means

The Azure BlobStorageIO ReadBuffer (blobstorageio.py:648) fetches object properties in __init__ and, if Azure returns HTTP 404, raises a standard IOError with errno ENOENT and 'Not found: <path>'. This makes a missing blob behave like a missing local file for Beam's file-based sources.

Solutions

  1. Verify the input path/blob exists (client.exists or az storage blob list) before running
  2. Correct the container/blob name in pipeline options
  3. Catch IOError with errno.ENOENT to handle missing inputs gracefully

Example fix

// before
with client.open(path, 'r') as f:
    data = f.read()
// after
if not client.exists(path):
    logging.warning('blob %s missing, using empty input', path)
    data = b''
else:
    with client.open(path, 'r') as f:
        data = f.read()
Defensive patterns

Strategy: try-catch

Validate before calling

import errno
if not client.exists(path):
    # avoid constructing a reader for a missing blob
    raise SystemExit(f'input blob missing: {path}')

Try / catch

import errno
try:
    reader = client.open(path, 'r')
except IOError as e:
    if e.errno == errno.ENOENT:
        logging.error('input blob not found: %s', path)
    else:
        raise

Prevention

When it happens

Trigger: Creating a reader for a blob path that does not exist (e.g. empty input pattern resolved to a nonexistent file, file deleted before read, wrong container).

Common situations: Pipeline input path typo; upstream stage failed silently so expected output blob is missing; case-sensitivity mismatches in blob names.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/io/azure/blobstorageio.py:648

        counter,
        time.time() - start_time)


class BlobStorageDownloader(Downloader):
  def __init__(self, client, path, buffer_size):
    self._client = client
    self._path = path
    self._container, self._blob = parse_azfs_path(path)
    self._buffer_size = buffer_size

    self._blob_to_download = self._client.get_blob_client(
        self._container, self._blob)

    try:
      properties = self._get_object_properties()
    except ResourceNotFoundError as http_error:
      if http_error.status_code == 404:
        raise IOError(errno.ENOENT, 'Not found: %s' % self._path)
      else:
        _LOGGER.error(
            'HTTP error while requesting file %s: %s', self._path, http_error)
        raise

    self._size = properties.size

  @retry.with_exponential_backoff(
      retry_filter=retry.retry_on_beam_io_error_filter)
  def _get_object_properties(self):
    return self._blob_to_download.get_blob_properties()

  @property
  def size(self):
    return self._size

  def get_range(self, start, end):
    # Download_blob first parameter is offset and second is length (exclusive).

View on GitHub (pinned to 12126d8942)