zylon-ai/private-gpt · error · ValueError

No reader registered for extension: {extension}

Error message

No reader registered for extension: {extension}

What it means

ReaderComponent.get_reader_by_extension looks up reader names for a file extension in the registry; if no reader is registered for that extension at all, it raises ValueError. This means the extension was never mapped (neither built-in defaults nor custom registrations cover it), so the system has no way to parse the file. It is distinct from error 204, which covers the name/extension combined lookup in get_reader.

Source

Thrown at private_gpt/components/readers/reader_component.py:33


@singleton
class ReaderComponent:
    @inject
    def __init__(
        self,
        settings: Settings,
        reader_registry: ReaderRegistry,
        reader_factory_registry: ReaderFactoryRegistry,
    ) -> None:
        self.settings = settings
        self.registry = reader_registry
        self.factory_registry = reader_factory_registry

    def get_reader_by_extension(self, extension: str) -> IngestionReader:
        reader_names = self.get_reader_names(extension=extension)
        if not reader_names:
            raise ValueError(f"No reader registered for extension: {extension}")
        return self.get_reader(reader_names[0], extension)

    def get_reader(
        self,
        name: str | None = None,
        extension: str | None = None,
    ) -> IngestionReader:
        reader_names = self.get_reader_names(name=name, extension=extension)
        if not reader_names:
            raise ValueError(f"No reader available for extension: {extension}")
        target_name = reader_names[0]
        factory = self.factory_registry.get_factory(target_name)
        return factory.create_reader(extension)

    def get_registered_reader_name(self, extension: str | None) -> str | None:
        return self.registry.get_reader_name(extension)

    def get_reader_names(

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Check the registry contents (get_reader_names / get_registered_reader_name) and confirm the exact extension string, lowercased and dot-prefixed, is registered.
  2. Register a reader for the extension: component.register_reader_factory(name, factory) plus register_extension_reader(ext, name).
  3. If the format is genuinely unsupported, convert the file to a supported format (e.g. .pdf, .txt, .csv) before ingestion.
  4. Normalize the extension (`Path(f).suffix.lower()`) before calling the API — mismatched case is a common silent cause.

Example fix

# before
reader = component.get_reader_by_extension(".DOCX")  # ValueError: No reader registered

# after
ext = Path(file_name).suffix.lower()
reader = component.get_reader_by_extension(ext)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

SUPPORTED = {".csv", ".tsv", ".psv", ".eml", ".pdf", ".txt", ".md", ".html"}  # adjust to your registration set

def can_ingest(file_name: str) -> bool:
    return Path(file_name).suffix.lower() in SUPPORTED

Try / catch

try:
    reader = component.get_reader_by_extension(ext)
except ValueError as e:
    logger.warning("Unsupported extension, skipping file: %s", e)
    return None

Prevention

When it happens

Trigger: Calling get_reader_by_extension(ext) for an extension absent from the reader registry — e.g. '.xyz', an extension whose reader was never registered, or after unregister_reader_factory removed the only reader for it.

Common situations: Ingesting an unsupported file type (.docx legacy, .heic, proprietary formats); forgetting to register a custom reader factory plus its extension mapping; a typo in the extension (uppercase '.PDF' vs '.pdf' if normalization is missing); disabling a reader at config time.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/afd1949262029d60. Report an issue: GitHub.