pallets/flask · error · RuntimeError

Unable to build URLs outside an active request without…

Error message

Unable to build URLs outside an active request without 'SERVER_NAME' configured. Also configure 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as needed.

What it means

Raised by Flask.url_for() (outside a request context) when no URL adapter can be constructed. Outside a request, Flask needs SERVER_NAME (and typically APPLICATION_ROOT/PREFERRED_URL_SCHEME) to build an absolute URL adapter; without them url_adapter is None.

Solutions

  1. Set SERVER_NAME in config: app.config['SERVER_NAME'] = 'example.com:5000'.
  2. Wrap the call in a request/test context: with app.test_request_context(): url_for('endpoint').
  3. Use app.app_context() plus SERVER_NAME when only an app context is available.

Example fix

// before
# outside any request, no SERVER_NAME
url = app.url_for('profile', user_id=5)  # raises
// after
app.config['SERVER_NAME'] = 'example.com'
url = app.url_for('profile', user_id=5)
Defensive patterns

Strategy: validation

Validate before calling

if not app.config.get('SERVER_NAME'):
    raise RuntimeError('SERVER_NAME must be set to build URLs outside a request')
app.url_for('endpoint')

Type guard

def can_build_url_offline(app) -> bool:
    return bool(app.config.get('SERVER_NAME'))

Try / catch

try:
    url = app.url_for('endpoint')
except RuntimeError as e:
    if 'SERVER_NAME' in str(e):
        url = build_urlManually(...)
    raise

Prevention

When it happens

Trigger: Calling app.url_for('endpoint') or url_for('endpoint', _external=True) in a script, background task, or test without a request context and without SERVER_NAME set in app.config.

Common situations: Generating URLs in a CLI command, celery task, or test fixture; deploying behind a proxy without setting SERVER_NAME; calling url_for at import time.

Related errors


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

Appendix: source

Thrown at src/flask/app.py:1188

                    endpoint = f"{blueprint_name}{endpoint}"
                else:
                    endpoint = endpoint[1:]

            # When in a request, generate a URL without scheme and
            # domain by default, unless a scheme is given.
            if _external is None:
                _external = _scheme is not None
        else:
            # If called by helpers.url_for, an app context is active,
            # use its url_adapter. Otherwise, app.url_for was called
            # directly, build an adapter.
            if ctx is not None:
                url_adapter = ctx.url_adapter
            else:
                url_adapter = self.create_url_adapter(None)

            if url_adapter is None:
                raise RuntimeError(
                    "Unable to build URLs outside an active request"
                    " without 'SERVER_NAME' configured. Also configure"
                    " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as"
                    " needed."
                )

            # When outside a request, generate a URL with scheme and
            # domain by default.
            if _external is None:
                _external = True

        # It is an error to set _scheme when _external=False, in order
        # to avoid accidental insecure URLs.
        if _scheme is not None and not _external:
            raise ValueError("When specifying '_scheme', '_external' must be True.")

        self.inject_url_defaults(endpoint, values)

View on GitHub (pinned to 3596b1ab61)