pallets/flask · error · ValueError

Resources can only be opened for reading.

Error message

Resources can only be opened for reading.

What it means

Raised by Scaffold.open_resource() when the requested file mode is not one of the read-only modes {"r", "rt", "rb"}. Resources are read-only by contract; the method rejects write/append modes to prevent accidental mutation of packaged files.

Solutions

  1. Use a read mode: app.open_resource('data.json', mode='r', encoding='utf-8').
  2. For writing, use open_instance_resource() or open() against an absolute writable path outside the package.
  3. If mutation is required, write to the instance folder via app.instance_path instead.

Example fix

// before
with app.open_resource('seed.json', mode='w') as f:  # raises
    f.write('{}')
// after
import os
path = os.path.join(app.instance_path, 'seed.json')
with open(path, 'w', encoding='utf-8') as f:
    f.write('{}')
Defensive patterns

Strategy: validation

Validate before calling

READ_MODES = {'r', 'rt', 'rb'}
if mode not in READ_MODES:
    raise ValueError(f'open_resource requires a read mode, got {mode!r}')
app.open_resource('data.json', mode=mode)

Type guard

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

Try / catch

try:
    with app.open_resource(path, mode=mode) as f:
        ...
except ValueError as e:
    if 'only be opened for reading' in str(e):
        # switch to writable path
        ...
    raise

Prevention

When it happens

Trigger: Calling app.open_resource('data.json', mode='w') or blueprint.open_resource('config.toml', mode='a') with any mode containing 'w', 'a', '+', or 'x'.

Common situations: Developer assumes open_resource mirrors open() semantics and tries to write to a bundled resource; porting code that used open() on resource paths.

Related errors


AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11). Data as JSON: /api/errors/6f388261c52242d5. Report an issue: GitHub.

Appendix: source

Thrown at src/flask/app.py:439

        ``app.py`` where the ``Flask`` app is defined, it can be opened
        with:

        .. code-block:: python

            with app.open_resource("schema.sql") as f:
                conn.executescript(f.read())

        :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)

    def open_instance_resource(
        self, resource: str, mode: str = "rb", encoding: str | None = "utf-8"
    ) -> t.IO[t.AnyStr]:
        """Open a resource file relative to the application's instance folder
        :attr:`instance_path`. Unlike :meth:`open_resource`, files in the
        instance folder can be opened for writing.

        :param resource: Path to the resource relative to :attr:`instance_path`.
        :param mode: Open the file in this mode.
        :param encoding: Open the file with this encoding when opening in text

View on GitHub (pinned to 3596b1ab61)