{"id":"4892a1ca3144b66f","repo":"pallets/flask","slug":"static-folder-must-be-set-to-serve-static-files-4892a1","errorCode":null,"errorMessage":"'static_folder' must be set to serve static_files.","messagePattern":"'static_folder' must be set to serve static_files\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/flask/blueprints.py","lineNumber":95,"sourceCode":"        if isinstance(value, timedelta):\n            return int(value.total_seconds())\n\n        return value  # type: ignore[no-any-return]\n\n    def send_static_file(self, filename: str) -> Response:\n        \"\"\"The view function used to serve files from\n        :attr:`static_folder`. A route is automatically registered for\n        this view at :attr:`static_url_path` if :attr:`static_folder` is\n        set.\n\n        Note this is a duplicate of the same method in the Flask\n        class.\n\n        .. versionadded:: 0.5\n\n        \"\"\"\n        if not self.has_static_folder:\n            raise RuntimeError(\"'static_folder' must be set to serve static_files.\")\n\n        # send_file only knows to call get_send_file_max_age on the app,\n        # call it here so it works for blueprints too.\n        max_age = self.get_send_file_max_age(filename)\n        return send_from_directory(\n            t.cast(str, self.static_folder), filename, max_age=max_age\n        )\n\n    def open_resource(\n        self, resource: str, mode: str = \"rb\", encoding: str | None = \"utf-8\"\n    ) -> t.IO[t.AnyStr]:\n        \"\"\"Open a resource file relative to :attr:`root_path` for reading. The\n        blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource`\n        method.\n\n        :param resource: Path to the resource relative to :attr:`root_path`.\n        :param mode: Open the file in this mode. Only reading is supported,\n            valid values are ``\"r\"`` (or ``\"rt\"``) and ``\"rb\"``.","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/blueprints.py#L77-L113","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass static_folder='static' (relative to the blueprint package) in the Blueprint(...) constructor.","If assets belong to the whole app, use the app's static route (url_for('static', ...)) instead of the blueprint's.","Set static_url_path too if you need a custom URL prefix for the blueprint's assets."],"exampleFix":"# before\nbp = Blueprint('admin', __name__)\n# after\nbp = Blueprint('admin', __name__, static_folder='static', static_url_path='/admin/static')","handlingStrategy":"validation","validationCode":"if bp.static_folder is None:\n    raise RuntimeError(\"Blueprint was created without static_folder; pass static_folder='static' to Blueprint(...) before using static routes\")","typeGuard":"def has_static(bp) -> bool:\n    return bp.static_folder is not None","tryCatchPattern":null,"preventionTips":["Pass static_folder= (and optionally static_url_path=) in the Blueprint constructor whenever you reference bp static files","Don't call send_static_file/url_for('bp.static', ...) on blueprints that only serve API routes","Add a startup assertion that every blueprint with templates referencing its static endpoint has static_folder set"],"tags":["flask","blueprint","static-files"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}