pallets/flask · error · AssertionError

View function mapping is overwriting an existing endpoint…

Error message

View function mapping is overwriting an existing endpoint function: {endpoint}

What it means

Flask stores view functions in a dict keyed by endpoint name (app.view_functions). add_url_rule checks if an endpoint already maps to a DIFFERENT callable; if so it raises AssertionError to prevent a silent override. Registering the same function again (e.g. re-import) is allowed.

Solutions

  1. Give each conflicting view a distinct endpoint via endpoint='unique_name', or rename one of the functions.
  2. Register blueprints with unique names (name= or name_prefix=) so blueprint endpoints do not collide with app-level endpoints.
  3. Check for duplicate route registration caused by importing the same module twice; deduplicate the imports.
  4. Inspect app.view_functions keys at startup to find the duplicate before it raises.

Example fix

// before
@app.route('/a')
def index(): ...
@app.route('/b')  # default endpoint 'index' collides
def index(): ...

// after
@app.route('/a')
def index(): ...
@app.route('/b', endpoint='index_b')
def index_b(): ...
Defensive patterns

Strategy: validation

Validate before calling

def assert_endpoint_free(app, endpoint):
    if endpoint in app.view_functions:
        raise ValueError(f'endpoint {endpoint!r} already registered to {app.view_functions[endpoint]!r}')

Type guard

def endpoint_is_unique(app, endpoint: str) -> bool:
    return endpoint not in app.view_functions

Try / catch

try:
    app.add_url_rule('/x', endpoint='x', view_func=fn)
except AssertionError as e:
    if 'overwriting an existing endpoint' in str(e):
        # choose a different endpoint name and retry
        raise

Prevention

When it happens

Trigger: Two different view functions resolving to the same endpoint (default endpoint = view_func.__name__); explicitly passing endpoint='x' to two distinct functions; a blueprint and an app route colliding on endpoint name; functools.partial or lambda views colliding on default name.

Common situations: Naming two views the same (e.g. two index functions in different modules), Flask's default endpoint-from-view-func colliding, blueprint registration without name_prefix producing colliding dotted endpoints, double-decorating the same function path.

Related errors


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

Appendix: source

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

                provide_automatic_options = (
                    "OPTIONS" not in methods
                    and self.config["PROVIDE_AUTOMATIC_OPTIONS"]
                )

        if provide_automatic_options:
            required_methods.add("OPTIONS")

        # Add the required methods now.
        methods |= required_methods

        rule_obj = self.url_rule_class(rule, methods=methods, **options)
        rule_obj.provide_automatic_options = provide_automatic_options  # type: ignore[attr-defined]

        self.url_map.add(rule_obj)
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError(
                    "View function mapping is overwriting an existing"
                    f" endpoint function: {endpoint}"
                )
            self.view_functions[endpoint] = view_func

    @t.overload
    def template_filter(self, name: T_template_filter) -> T_template_filter: ...
    @t.overload
    def template_filter(
        self, name: str | None = None
    ) -> t.Callable[[T_template_filter], T_template_filter]: ...
    @setupmethod
    def template_filter(
        self, name: T_template_filter | str | None = None
    ) -> T_template_filter | t.Callable[[T_template_filter], T_template_filter]:
        """Decorate a function to register it as a custom Jinja filter. The name
        is optional. The decorator may be used without parentheses.

View on GitHub (pinned to 3596b1ab61)