roboflow/supervision · error · Exception

Cannot append to CSV: The file '{self.file_name}' is not ope

Error message

Cannot append to CSV: The file '{self.file_name}' is not open.

What it means

CSVSink raises this generic Exception from append() when its internal csv writer is None, i.e. the sink is not inside its opened context. CSVSink opens the file lazily via the context-manager protocol (__enter__), so append() is only valid inside a `with CSVSink(...) as sink:` block.

Source

Thrown at src/supervision/detection/tools/csv_sink.py:214

            parsed_rows.append(row)
        return parsed_rows

    def append(
        self, detections: Detections, custom_data: dict[str, Any] | None = None
    ) -> None:
        """
        Append detection data to the CSV file.

        Args:
            detections: The detection data.
            custom_data: Custom data to include. Scalars, dictionaries, and
                other non-sequence values are broadcast to every detection in
                this batch. NumPy arrays, lists, and tuples with length equal
                to ``len(detections)`` are sliced per detection; other lists
                and tuples are broadcast unchanged.
        """
        if not self.writer:
            raise Exception(
                f"Cannot append to CSV: The file '{self.file_name}' is not open."
            )
        field_names = CSVSink.parse_field_names(detections, custom_data)
        if not self.header_written:
            self.field_names = field_names
            self.writer.writerow(field_names)
            self.header_written = True

        if field_names != self.field_names:
            logger.warning(
                "Field names do not match the header. Expected: %s, given: %s",
                self.field_names,
                field_names,
            )

        parsed_rows = CSVSink.parse_detection_data(detections, custom_data)
        for row in parsed_rows:
            self.writer.writerow(

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Wrap usage in the context manager: with CSVSink('out.csv') as sink: sink.append(detections).
  2. Keep the entire detection loop inside the with block so append always has an open writer.
  3. If appending from multiple places, open the sink once and pass it down while the context is still active.
  4. Do not call append() after __exit__; create a new CSVSink for a new session.

Example fix

# before
sink = CSVSink("out.csv")
sink.append(detections)  # Exception: file is not open

# after
with CSVSink("out.csv") as sink:
    for frame in video:
        detections = model(frame)
        sink.append(detections)
Defensive patterns

Strategy: try-catch

Validate before calling

if getattr(sink, "writer", None) is None:
    raise RuntimeError("CSVSink not open; use 'with CSVSink(...) as sink:'")
sink.append(detections)

Try / catch

try:
    sink.append(detections)
except Exception as exc:
    if "not open" in str(exc):
        logger.error("CSVSink used outside its context manager")
        raise
    raise

Prevention

When it happens

Trigger: Creating sink = CSVSink('out.csv') and calling sink.append(detections) without entering the with block; or calling append() after the with block has exited (file already closed).

Common situations: Migrating code that assumed the constructor opens the file (older examples or other sinks like JSONSink behave differently); storing the sink on a class and appending from another method after the context exited; reusing a sink across video loops where only the first loop is inside the with.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/d1d60fff46db60b9. Report an issue: GitHub.