pallets/flask · error · ValueError

If an instance path is provided it must be absolute. A…

Error message

If an instance path is provided it must be absolute. A relative path was given instead.

What it means

App.__init__ accepts an optional instance_path. If you supply one that is not absolute (os.path.isabs returns False), it raises ValueError. When instance_path is None Flask auto-discovers it; the explicit-value path strictly requires an absolute filesystem path because relative paths would be ambiguous depending on the process cwd.

Solutions

  1. Pass an absolute path: Flask(__name__, instance_path='/abs/path/to/instance').
  2. Omit instance_path entirely so Flask calls auto_find_instance_path() and derives it from root_path.
  3. Build the absolute path from the app location: instance_path=os.path.join(os.path.dirname(__file__), 'instance') with abspath.

Example fix

# before
app = Flask(__name__, instance_path='instance')  # ValueError

# after
app = Flask(__name__)  # auto-find
# or
app = Flask(__name__, instance_path=os.path.abspath('instance'))
Defensive patterns

Strategy: validation

Validate before calling

import os

def is_absolute_path(p: str) -> bool:
    return os.path.isabs(p)

Type guard

import os

def is_absolute_path(p: str) -> bool:
    return os.path.isabs(p)

Try / catch

import os
try:
    app = Flask(__name__, instance_path=instance_path)
except ValueError:
    app = Flask(__name__, instance_path=os.path.abspath(instance_path))

Prevention

When it happens

Trigger: Constructing Flask(__name__, instance_path='instance') or Flask(__name__, instance_path='./instance')—any relative path. The check is elif not os.path.isabs(instance_path) on the non-None branch.

Common situations: Hardcoding a relative instance folder. Copying example code that used a relative path on a different OS. Assuming Flask resolves relative paths against the app root (it does not—it requires an absolute path or auto-detection).

Related errors


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

Appendix: source

Thrown at src/flask/sansio/app.py:303

        host_matching: bool = False,
        subdomain_matching: bool = False,
        template_folder: str | os.PathLike[str] | None = "templates",
        instance_path: str | None = None,
        instance_relative_config: bool = False,
        root_path: str | None = None,
    ) -> None:
        super().__init__(
            import_name=import_name,
            static_folder=static_folder,
            static_url_path=static_url_path,
            template_folder=template_folder,
            root_path=root_path,
        )

        if instance_path is None:
            instance_path = self.auto_find_instance_path()
        elif not os.path.isabs(instance_path):
            raise ValueError(
                "If an instance path is provided it must be absolute."
                " A relative path was given instead."
            )

        #: Holds the path to the instance folder.
        #:
        #: .. versionadded:: 0.8
        self.instance_path = instance_path

        #: The configuration dictionary as :class:`Config`.  This behaves
        #: exactly like a regular dictionary but supports additional methods
        #: to load a config from files.
        self.config = self.make_config(instance_relative_config)

        #: An instance of :attr:`aborter_class` created by
        #: :meth:`make_aborter`. This is called by :func:`flask.abort`
        #: to raise HTTP errors, and can be called directly as well.
        #:

View on GitHub (pinned to 3596b1ab61)