makeplane/plane · error · ValueError

Unsupported format: {format_type}. Available: {list(self.FOR

Error message

Unsupported format: {format_type}. Available: {list(self.FORMATTERS.keys())}

What it means

ValueError raised in `Exporter.__init__` (exporter.py:31) when `format_type` is not a key of the `FORMATTERS` class dict, which contains exactly `csv`, `json`, and `xlsx` (case-sensitive, lowercase). Construction fails before any export runs. The error message lists the available keys to aid diagnosis.

Source

Thrown at apps/api/plane/utils/exporters/exporter.py:31

    """Generic exporter class that handles data exports using different formatters."""

    # Available formatters
    FORMATTERS = {
        "csv": CSVFormatter,
        "json": JSONFormatter,
        "xlsx": XLSXFormatter,
    }

    def __init__(self, format_type: str, schema_class: Type, options: Dict[str, Any] = None):
        """Initialize exporter with specified format type and schema.

        Args:
            format_type: The export format (csv, json, xlsx)
            schema_class: The schema class to use for field definitions
            options: Optional formatting options
        """
        if format_type not in self.FORMATTERS:
            raise ValueError(f"Unsupported format: {format_type}. Available: {list(self.FORMATTERS.keys())}")

        self.format_type = format_type
        self.schema_class = schema_class
        self.formatter = self.FORMATTERS[format_type]()
        self.options = options or {}

    def export(
        self,
        filename: str,
        data: Union[QuerySet, List[dict]],
        fields: List[str] = None,
    ) -> tuple[str, str | bytes]:
        """Export data using the configured formatter and return (filename, content).

        Args:
            filename: The filename for the export (without extension)
            data: Either a Django QuerySet or a list of already-serialized dicts
            fields: Optional list of field names to include in export

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Pass exactly 'csv', 'json', or 'xlsx' (lowercase) as format_type.
  2. Validate/normalize the format from user input before constructing: `fmt = fmt.lower(); assert fmt in Exporter.get_available_formats()`.
  3. To support a new format, register a formatter via `Exporter.register_formatter('xml', XMLFormatter)` before constructing.
  4. If unsure, call `Exporter.get_available_formats()` to list supported keys dynamically rather than hardcoding.

Example fix

# before
exporter = Exporter(format_type=request.GET.get('format', 'csv'), schema_class=Schema)
# user sends ?format=XML -> ValueError

# after
fmt = request.GET.get('format', 'csv').lower()
if fmt not in Exporter.get_available_formats():
    return Response({'error': 'Unsupported format'}, status=400)
exporter = Exporter(format_type=fmt, schema_class=Schema)
Defensive patterns

Strategy: validation

Validate before calling

from plane.utils.exporters.exporter import Exporter

def is_supported_format(fmt: str) -> bool:
    return fmt in Exporter.FORMATTERS  # {'csv','json','xlsx'}

# normalize before constructing:
# fmt = fmt.strip().lower()

Type guard

from plane.utils.exporters.exporter import Exporter

def is_supported_format(value: str) -> bool:
    return isinstance(value, str) and value in Exporter.FORMATTERS

Try / catch

try:
    exporter = Exporter(format_type=fmt, schema_class=Schema)
except ValueError as e:
    if 'Unsupported format' in str(e):
        return bad_request({'available': Exporter.get_available_formats()})

Prevention

When it happens

Trigger: Constructing `Exporter(format_type=..., schema_class=...)` with a format not in {csv, json, xlsx}: e.g. 'XML', 'xls', 'CSV' (uppercase), 'pdf', or a user-supplied format string that wasn't validated.

Common situations: User-facing export dropdown that passes an unvalidated format query param; case mismatch ('CSV' vs 'csv'); requesting a format the schema/README mentions in examples (like 'xml') but that has no registered formatter; new format added to the UI but not to FORMATTERS.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/f65085a29bce8963. Report an issue: GitHub.