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/

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

  1. Read which of the four messages you got; it tells you if the name, the namespace, or the arguments are wrong.
  2. Compare your arguments with the "pattern(s) tried" regex.
  3. App has app_name? Use app:name everywhere, including redirect() and {% url %}.
  4. '' 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.