Flask: AssertionError: View function mapping is overwriting an existing endpoint function
This error occurs when Python tries to register multiple Flask routes whose view functions share the same name. Use unique view function names, declare explicit endpoint='name' arguments, or use Blueprints.
Root Cause Analysis
This error occurs when Python attempts to register a route with @app.route() or app.add_url_rule() where the endpoint identifier collides with an already registered route handler.
Root Cause 1: Duplicate View Function Names in the Same Module
By default, Flask uses the function's __name__ attribute as its internal endpoint name. If two route decorators in the same file define functions named index() or main(), Flask attempts to register the second function under the same endpoint key 'index', triggering AssertionError: View function mapping is overwriting an existing endpoint function: index.
Root Cause 2: Copy-Pasting Route Handlers Without Renaming
Developers frequently copy-paste endpoint templates (e.g. @app.route('/users') def get_data(): ... and @app.route('/items') def get_data(): ...) and forget to rename the underlying Python function definition.
Root Cause 3: Non-Namespaced Blueprints
When multiple Blueprints define views with generic names like list() or create() and are registered without distinct Blueprint names, endpoint clashes occur during application startup.
Root Cause 4: Custom Decorators Without functools.wraps
When wrapping view functions with custom decorators (for authentication, logging, or caching) without applying @functools.wraps(f), the decorated function's __name__ is overwritten with the wrapper function's name (e.g. 'wrapper'), causing all decorated routes to collide under the endpoint name 'wrapper'.
Reproduction Code (MCVE)
# Simulating Flask route registry duplicate endpoint detection
view_function_endpoints = {}
def add_url_rule(rule: str, endpoint: str, view_func):
if endpoint in view_function_endpoints:
existing_func = view_function_endpoints[endpoint]
raise AssertionError(
f"AssertionError: View function mapping is overwriting an existing endpoint function: {endpoint}. "
f"An existing function '{existing_func.__name__}' is already registered for this endpoint name."
)
view_function_endpoints[endpoint] = view_func
def main():
return "Home Page"
def main_duplicate():
return "Dashboard"
# Registering two functions with the same endpoint name 'main'
add_url_rule("/", "main", main)
add_url_rule("/dashboard", "main", main_duplicate)
Solution 1: Use Unique Function Names or Explicit endpoint Parameter
Provide distinct function names for each route, or specify explicit unique endpoint='custom_name' arguments in @app.route().
from flask import Flask
app = Flask(__name__)
# Solution 1: Use unique function names or explicit endpoint arguments in @app.route
@app.route("/")
def home():
return "Home Page"
@app.route("/dashboard", endpoint="dashboard_view")
def dashboard():
return "User Dashboard"
# Test route registration
endpoints = [rule.endpoint for rule in app.url_map.iter_rules()]
print("Registered Flask endpoints:", endpoints)
assert "home" in endpoints
assert "dashboard_view" in endpoints
Solution 2: Use Flask Blueprints and @functools.wraps for Decorators
Group routes into modular Blueprints to automatically namespace endpoints as blueprint_name.function_name, and always apply @functools.wraps on decorators.
from flask import Flask, Blueprint
import functools
# Solution 2: Use Blueprints to namespace endpoints cleanly
auth_bp = Blueprint("auth", __name__, url_prefix="/auth")
api_bp = Blueprint("api", __name__, url_prefix="/api")
@auth_bp.route("/status")
def status():
return {"module": "auth", "ok": True}
@api_bp.route("/status")
def status():
return {"module": "api", "ok": True}
app = Flask(__name__)
app.register_blueprint(auth_bp)
app.register_blueprint(api_bp)
bp_endpoints = [rule.endpoint for rule in app.url_map.iter_rules()]
print("Blueprint namespaced endpoints:", bp_endpoints)
assert "auth.status" in bp_endpoints
assert "api.status" in bp_endpoints
Whenever you write a custom decorator for Flask routes (such as @login_required or @admin_only), always import functools and decorate the wrapper with @functools.wraps(view_func). Without @functools.wraps, all decorated view functions inherit the name 'wrapper', and registering more than one decorated route will immediately crash with this AssertionError.
Another edge case is using url_for('status') when Blueprints are active: you must specify the full endpoint path url_for('auth.status') or url_for('.status') within the Blueprint.
Contrast this AssertionError with BuildError: Could not build url for endpoint: The AssertionError happens at application startup during routing table initialization, whereas BuildError happens at runtime when url_for() is called with an invalid or non-existent endpoint name.