pallets/flask · error · ValueError

Resources can only be opened for reading.

Error message

Resources can only be opened for reading.

What it means

Blueprint.open_resource (like Flask.open_resource) only supports read modes — it validates mode against {'r', 'rt', 'rb'} and raises ValueError otherwise. Resources are meant to be read-only package data relative to root_path; writing to installed package directories is unsupported and often impossible (zip imports, read-only installs).

Source

Thrown at src/flask/blueprints.py:121

    def open_resource(
        self, resource: str, mode: str = "rb", encoding: str | None = "utf-8"
    ) -> t.IO[t.AnyStr]:
        """Open a resource file relative to :attr:`root_path` for reading. The
        blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource`
        method.

        :param resource: Path to the resource relative to :attr:`root_path`.
        :param mode: Open the file in this mode. Only reading is supported,
            valid values are ``"r"`` (or ``"rt"``) and ``"rb"``.
        :param encoding: Open the file with this encoding when opening in text
            mode. This is ignored when opening in binary mode.

        .. versionchanged:: 3.1
            Added the ``encoding`` parameter.
        """
        if mode not in {"r", "rt", "rb"}:
            raise ValueError("Resources can only be opened for reading.")

        path = os.path.join(self.root_path, resource)

        if mode == "rb":
            return open(path, mode)  # pyright: ignore

        return open(path, mode, encoding=encoding)

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Use a read mode: bp.open_resource('data.txt') or mode='rb' for binary.
  2. For writable data, open a path under app.instance_path (or another writable directory) with the builtin open() instead.
  3. If you only need the file contents, consider importlib.resources for package data.

Example fix

# before
with bp.open_resource('cache.json', mode='w') as f: ...
# after
import os
with open(os.path.join(app.instance_path, 'cache.json'), 'w') as f: ...
Defensive patterns

Strategy: validation

Validate before calling

mode = 'rb'  # only read modes allowed
assert 'w' not in mode and 'a' not in mode and '+' not in mode, "open_resource only supports read modes"
with bp.open_resource('data/schema.sql', mode) as f:
    data = f.read()

Type guard

def is_read_mode(mode: str) -> bool:
    return mode in ('r', 'rt', 'rb')

Prevention

When it happens

Trigger: Calling bp.open_resource('data.txt', mode='w'), 'a', 'r+', 'wb', or any mode string outside 'r'/'rt'/'rb'.

Common situations: Trying to persist user data or caches next to package code; porting open() calls to open_resource without adjusting the mode; templating tools writing generated files through the resource API.

Related errors


AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31). Data as JSON: /data/errors/e2f2ac59eabf1839.json. Report an issue: GitHub ↗.