pallets/flask · error · RuntimeError

'static_folder' must be set to serve static_files.

Error message

'static_folder' must be set to serve static_files.

What it means

Blueprint.send_static_file serves files from the blueprint's configured static_folder. If the blueprint was created without static_folder (has_static_folder is False), there is no directory to serve from, so Flask raises RuntimeError rather than guessing a path (src/flask/blueprints.py:95).

Source

Thrown at src/flask/blueprints.py:95

        if isinstance(value, timedelta):
            return int(value.total_seconds())

        return value  # type: ignore[no-any-return]

    def send_static_file(self, filename: str) -> Response:
        """The view function used to serve files from
        :attr:`static_folder`. A route is automatically registered for
        this view at :attr:`static_url_path` if :attr:`static_folder` is
        set.

        Note this is a duplicate of the same method in the Flask
        class.

        .. versionadded:: 0.5

        """
        if not self.has_static_folder:
            raise RuntimeError("'static_folder' must be set to serve static_files.")

        # send_file only knows to call get_send_file_max_age on the app,
        # call it here so it works for blueprints too.
        max_age = self.get_send_file_max_age(filename)
        return send_from_directory(
            t.cast(str, self.static_folder), filename, max_age=max_age
        )

    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"``.

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Pass static_folder='static' (relative to the blueprint package) in the Blueprint(...) constructor.
  2. If assets belong to the whole app, use the app's static route (url_for('static', ...)) instead of the blueprint's.
  3. Set static_url_path too if you need a custom URL prefix for the blueprint's assets.

Example fix

# before
bp = Blueprint('admin', __name__)
# after
bp = Blueprint('admin', __name__, static_folder='static', static_url_path='/admin/static')
Defensive patterns

Strategy: validation

Validate before calling

if bp.static_folder is None:
    raise RuntimeError("Blueprint was created without static_folder; pass static_folder='static' to Blueprint(...) before using static routes")

Type guard

def has_static(bp) -> bool:
    return bp.static_folder is not None

Prevention

When it happens

Trigger: Calling bp.send_static_file('style.css') or hitting url_for('bp.static', filename=...) on a Blueprint constructed without static_folder=, or with static_folder=None.

Common situations: Assuming blueprints inherit the app's 'static' folder (they don't); setting static_url_path but forgetting static_folder; copying app-level code into a blueprint; typo in the static_folder path making it unset in refactors.

Related errors


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