Django NoReverseMatch (tested)
Django raises NoReverseMatch when reverse(), redirect() or {% url %} cannot build a URL. The message says which part is wrong: the name, the namespace, or the arguments. Here is each case, measured.
Setup
One view, path('post/<int:pk>/', detail, name='post-detail'), mounted two ways: flat in urls_flat.py, and through include('blog.urls') with app_name = 'blog' in urls_ns.py:
from django.urls import path
from django.http import HttpResponse
def detail(request, pk): return HttpResponse(str(pk))
app_name = 'blog'
urlpatterns = [path('post/<int:pk>/', detail, name='post-detail')]
from django.urls import path, include
urlpatterns = [path('blog/', include('blog.urls'))] # app_name='blog' -> namespace 'blog'
from django.urls import path
from blog.urls import detail
urlpatterns = [path('post/<int:pk>/', detail, name='post-detail')] # no namespace
1. The four messages, and what each one means
from common import *
settings.configure(ROOT_URLCONF='urls_flat', INSTALLED_APPS=['blog'])
django.setup()
from django.urls import reverse, NoReverseMatch
calls = [("post_detail", {}), # typo: _ vs -
("post-detail", {}), # missing pk
("post-detail", {'args': ['abc']}), # pk not an int
("post-detail", {'kwargs': {'id': 1}}), # wrong kwarg name
("post-detail", {'args': [1]})]
for name, kw in calls:
try:
print(name, kw, '->', reverse(name, **kw))
except NoReverseMatch as e:
print(name, kw, '->', 'NoReverseMatch:', e)
Output:
post_detail {} -> NoReverseMatch: Reverse for 'post_detail' not found. 'post_detail' is not a valid view function or pattern name.
post-detail {} -> NoReverseMatch: Reverse for 'post-detail' with no arguments not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9]+)/\\Z']
post-detail {'args': ['abc']} -> NoReverseMatch: Reverse for 'post-detail' with arguments '('abc',)' not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9]+)/\\Z']
post-detail {'kwargs': {'id': 1}} -> NoReverseMatch: Reverse for 'post-detail' with keyword arguments '{'id': 1}' not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9]+)/\\Z']
post-detail {'args': [1]} -> /post/1/
'X' is not a valid view function or pattern name: no URL pattern has thatname=. Check spelling (_vs-) and, for apps withapp_name, the namespace prefix (section 2).with no arguments not found. 1 pattern(s) tried: the name exists but the pattern needs a value (pk) you did not pass.with arguments '('abc',)' not found: a value was passed but does not match the converter.<int:pk>becomes[0-9]+, as the "tried" regex shows.with keyword arguments '{'id': 1}': kwargs must use the names in the pattern (pk, notid).
2. Namespaces: 'blog' is not a registered namespace
from common import *
settings.configure(ROOT_URLCONF='urls_ns', INSTALLED_APPS=['blog'])
django.setup()
from django.urls import reverse, NoReverseMatch
for name in ['post-detail', 'blog:post-detail', 'blogs:post-detail']:
try:
print(name, '->', reverse(name, args=[1]))
except NoReverseMatch as e:
print(name, '->', 'NoReverseMatch:', e)
Output:
post-detail -> NoReverseMatch: Reverse for 'post-detail' not found. 'post-detail' is not a valid view function or pattern name.
blog:post-detail -> /blog/post/1/
blogs:post-detail -> NoReverseMatch: 'blogs' is not a registered namespace
Once blog/urls.py sets app_name = 'blog', its names only exist as blog:post-detail; the bare name fails with the "not a valid view function or pattern name" message. A misspelled or unknown prefix gives 'blogs' is not a registered namespace: the prefix must match an app_name (or include(..., namespace=...)) that is actually included from ROOT_URLCONF.
3. In templates: arguments '('',)' means an empty variable
from common import *
settings.configure(ROOT_URLCONF='urls_ns', INSTALLED_APPS=['blog'],
TEMPLATES=[{'BACKEND': 'django.template.backends.django.DjangoTemplates'}])
django.setup()
from django.template import engines
from django.urls import NoReverseMatch
t = engines['django'].from_string
for src, ctx in [("{% url 'blog:post-detail' post.pk %}", {'post': {'pk': ''}}),
("{% url 'blog:post-detail' post.pk %}", {}),
("{% url 'blog:post-detail' pk=post.pk %}", {'post': {'pk': 7}})]:
try:
print(src, ctx, '->', t(src).render(ctx))
except NoReverseMatch as e:
print(src, ctx, '->', 'NoReverseMatch:', e)
Output:
{% url 'blog:post-detail' post.pk %} {'post': {'pk': ''}} -> NoReverseMatch: Reverse for 'post-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['blog/post/(?P<pk>[0-9]+)/\\Z']
{% url 'blog:post-detail' post.pk %} {} -> NoReverseMatch: Reverse for 'post-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['blog/post/(?P<pk>[0-9]+)/\\Z']
{% url 'blog:post-detail' pk=post.pk %} {'post': {'pk': 7}} -> /blog/post/7/
The {% url %} tag turns a missing context variable into an empty string, so with arguments '('',)' almost always means the object was not in the context (wrong variable name, or a loop variable used outside the loop) or its pk is empty, e.g. an object that has not been saved yet. Note the message shows the name without its namespace.
Checklist
- Read which of the four messages you got; it tells you if the name, the namespace, or the arguments are wrong.
- Compare your arguments with the "pattern(s) tried" regex.
- App has
app_name? Useapp:nameeverywhere, includingredirect()and{% url %}. ''in the arguments? Check the template context.
Related: Django TemplateDoesNotExist.
Frequently asked questions
What does 'is not a valid view function or pattern name' mean?
No URL pattern has that name. Check spelling, and if the app's urls.py sets app_name, use the namespaced name like 'blog:post-detail'.
Why does NoReverseMatch show arguments '('',)'?
The {% url %} tag got an empty value, usually a variable missing from the template context or an unsaved object's pk.
How do I fix 'X is not a registered namespace'?
The prefix before the colon must match an app_name or include(namespace=...) that is included from ROOT_URLCONF.
Written with AI assistance. Measured on 2026-10-23 with Django 6.1.2 and Python 3.14.7 (python:3-alpine in Docker). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and Django are free.