pallets/flask · error · ValueError

'endpoint' may not contain a dot '.' character.

Error message

'endpoint' may not contain a dot '.' character.

What it means

A ValueError from `Blueprint.add_url_rule` (src/flask/sansio/blueprints.py:427-428). Blueprint endpoints are automatically prefixed with the blueprint's (possibly nested, dot-joined) name to form `blueprint.endpoint`; a dot inside the local endpoint segment would fake an extra nesting level and break `url_for` resolution, so it's rejected. The companion check on line 430-431 applies the same rule to `view_func.__name__` since that supplies the default endpoint.

Source

Thrown at src/flask/sansio/blueprints.py:428

        extend(self.template_context_processors, app.template_context_processors)

    @setupmethod
    def add_url_rule(
        self,
        rule: str,
        endpoint: str | None = None,
        view_func: ft.RouteCallable | None = None,
        provide_automatic_options: bool | None = None,
        **options: t.Any,
    ) -> None:
        """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for
        full documentation.

        The URL rule is prefixed with the blueprint's URL prefix. The endpoint name,
        used with :func:`url_for`, is prefixed with the blueprint's name.
        """
        if endpoint and "." in endpoint:
            raise ValueError("'endpoint' may not contain a dot '.' character.")

        if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__:
            raise ValueError("'view_func' name may not contain a dot '.' character.")

        self.record(
            lambda s: s.add_url_rule(
                rule,
                endpoint,
                view_func,
                provide_automatic_options=provide_automatic_options,
                **options,
            )
        )

    @t.overload
    def app_template_filter(self, name: T_template_filter) -> T_template_filter: ...
    @t.overload
    def app_template_filter(

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Use only the local segment as the endpoint (`endpoint='get_x'`); Flask prepends the blueprint name automatically, and `url_for('api.get_x')` still works.
  2. For real hierarchy, nest blueprints (`parent.register_blueprint(child)`) instead of encoding dots in endpoint names.
  3. If endpoints are generated from module paths, sanitize them: `path.replace('.', '_')` or take the last segment.

Example fix

# before
@bp.route("/items", endpoint="api.list_items")
def list_items(): ...

# after
@bp.route("/items", endpoint="list_items")
def list_items(): ...
# url_for("api.list_items") — prefix added by the blueprint
Defensive patterns

Strategy: validation

Validate before calling

if '.' in endpoint:
    raise ValueError('blueprint endpoint must not contain dots')
bp.add_url_rule('/x', endpoint=endpoint, view_func=view)

Type guard

def is_valid_bp_endpoint(endpoint):
    return isinstance(endpoint, str) and '.' not in endpoint

Prevention

When it happens

Trigger: `@bp.route('/x', endpoint='api.get_x')` or `bp.add_url_rule('/x', 'users.list', f)` — any explicit endpoint containing '.' on a blueprint. Also hit indirectly when a view function's `__name__` contains a dot (e.g. assigned dynamically), which raises the sibling 'view_func' variant.

Common situations: Habits carried over from app-level `url_for('bp.view')` strings — developers write the fully qualified name as the endpoint; migrating pre-2.0 code where dotted endpoints on blueprints only warned; generating endpoints from dotted module paths in plugin loaders.

Related errors


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