apache/cassandra · error · IOError

Can't open %r for reading: %s

Error message

Can't open %r for reading: %s

What it means

When COPY FROM opens one of the comma-separated input files, an IOError from open() is re-raised with a clearer message naming the file and the underlying OS reason. It wraps the raw errno error so the user knows which path failed.

Source

Thrown at pylib/cqlshlib/copyutil.py:897

        self.skip_rows = options.copy['skiprows']
        self.fname = fname
        self.sources = None  # might be initialised directly here? (see CASSANDRA-17350)
        self.num_sources = 0
        self.current_source = None
        self.num_read = 0

    @staticmethod
    def get_source(paths):
        """
         Return a source generator. Each source is a named tuple
         wrapping the source input, file name and a boolean indicating
         if it requires closing.
        """
        def make_source(fname):
            try:
                return open(fname, 'r')
            except IOError as e:
                raise IOError("Can't open %r for reading: %s" % (fname, e))

        for path in paths.split(','):
            path = path.strip()
            if os.path.isfile(path):
                yield make_source(path)
            else:
                result = glob.glob(path)
                if len(result) == 0:
                    raise IOError("Can't open %r for reading: no matching file found" % (path,))

                for f in result:
                    yield make_source(f)

    def start(self):
        self.sources = self.get_source(self.fname)
        self.next_source()

    @property

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Check and fix file permissions (chmod/chown) so the cqlsh process can read the file
  2. Verify the file still exists and the path is correct at the time of the COPY
  3. Run cqlsh as a user with read access, or copy the file somewhere readable

Example fix

// before
COPY t FROM '/root/export/data.csv';  # permission denied
// after
$ chmod o+r /root/export/data.csv
COPY t FROM '/root/export/data.csv';
Defensive patterns

Strategy: try-catch

Validate before calling

import os
for p in path.split(','):
    p = p.strip()
    if not (os.path.isfile(p) and os.access(p, os.R_OK)):
        raise SystemExit(f"Cannot read {p}")

Try / catch

try:
    run_copy_from(fname)
except IOError as e:
    print(f"Input file unreadable: {e}")  # fix perms/path before retrying

Prevention

When it happens

Trigger: COPY FROM 'file.csv' where the path exists in os.path.isfile (so it passed the isfile check or was produced by glob) but open('r') still raises IOError — e.g. permission denied, a race where the file is deleted between the isfile check and open, or a directory-like special file.

Common situations: File owned by another user / no read permission (common when cqlsh runs as a different user than the one who created the export), file deleted by a concurrent job, path on an unmounted or network volume.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/f5cb170dbd02184c. Report an issue: GitHub.