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
- Pass an absolute path: Flask(__name__, instance_path='/abs/path/to/instance').
- Omit instance_path entirely so Flask calls auto_find_instance_path() and derives it from root_path.
- 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
- Pass instance_path as an absolute path or omit it for auto-detection.
- Build instance paths with os.path.abspath(os.path.join(basedir, 'instance')).
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
- A valid Flask application was not obtained from
- Allowed methods must be a list of strings, for example…
- Could not import .
- Could not locate a Flask application. Use the 'flask --app'…
- 'name' may not be empty.
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)