escaped z added to end of regex pattern causes NoReverseMatch error.

1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)\\Z']

This is not my pattern. I’ve never seen, let alone added, an escaped z to any regex pattern. I looked at the source code and there is no escaped z at the end of that, either. I have to get rid of this thing because it is making all my slug urls fail. If I remove it manually, then I get my match. But this site has thousands of pages, so manual won’t scale. Please advise. Thank you.

Please post the entries in your urls.py file that end up generating these patterns.
(Something obviously seems wrong because of the < text within the pattern. It almost appears as if something is html encoding your path patterns.)

No, it was a proper angle bracket. I keep a log of my work in an html file, so when I posted there I changed the opening angle bracket to the html entity.

As for my urls.py, this same issue is now occurring on a different model. I tested it also on regex101 and got the same result: as soon as I took \Z out of the pattern, regex101 reports a match: regex101 result

This is the one from today:

app_name = 'code'
urlpatterns = [
    path('<codekind>/', views.codewithkids, name='codewithkids_url'),
    path('<codekind>/<slug>/', views.codedetail, name='codedetail_url')
]

And this is the one from yesterday:

urlpatterns = [
    path('', views.caselist, name='caselist_url'),
    path('<slug:slug>', views.casedetail, name='casedetail_url'),
]

The Django exception:

Reverse for 'codedetail_url' with keyword arguments '{'slug': '10-usce-armed-forces'}' not found. 1 pattern(s) tried: ['(?P<twodigit>[^/]+)/code/(?P<codekind>[^/]+)/(?P<slug>[^/]+)/\\Z']

Note that I trimmed this to only the relevant part, i.e., the slug ‘10-usce-armed-forces’ does not match the pattern (?P[^/]+)/\Z - which is right, because the is no ‘\Z’ in any of my slugs. That’s why I have to find a way to get rid of this thing, and soon!

Also, note that this slug regex pattern is different from the one yesterday: (?P[^/]+)/\Z vs
(?P[-a-zA-Z0-9_]+)\Z. I don’t think that matters, however. It’s only the ‘\Z’ that is making these matches fail.

Thanx.

Something is happening to your path entries - something is altering your urlpatterns list or you’ve got null characters in your pattern string.

Do you have any code that is dynamically altering or modifying your urls?
Did you copy/paste these urls from some other source into your urls.py file?

You could try deleting those url patterns and retyping them.

Dear Ken,
First, let me just say ‘Thanks’ for your help.
The only dynamic part of my urls that I know of is what Django does with path conversion and regex
matching.
I tried the find, count, and replace methods for None and ‘’. exactly the same error
I tried retyping the path by hand - exactly the same error
I tried prepending ‘r’ for raw string. exactly the same error
I tried appending ‘$’. Now I get:
WARNINGS:
?: (2_0.W001) Your URL pattern ‘//$’ [name=‘codedetail_url’] has a route that contains ‘(?P<’, begins with a ‘^’, or ends with a ‘$’. This was likely an oversight when migrating to django.urls.path().

Note the raw string ‘r’ did not trigger a warning.
I tried appending ‘\Z’. exactly the same error, but now the regex pattern ends
with ‘(?P[^/]+)/\\Z\Z’]

I also returned to regex101 to test for \Z. But it turns out that if you put \Z in the pattern it
will match even before you put your string in. This is because \Z is a zero-width regex anchor that
means ‘end of input’ and is located before the newline, if there is one. At least I have expanded
my regex knowledge. Heretofore I thought ‘$’ was the only terminal anchor.

Here’s what is happening: When Django evaluates my path, it applies some sort of algorithm that
determines what regex pattern to apply, and then applies it. I was able to find this in the source
code:

https://docs.djangoproject.com/en/3.2/_modules/django/urls/converters/
class SlugConverter(StringConverter):
regex = ‘[-a-zA-Z0-9_]+’

The problem here is that this page vanishes from the docs for any Django version after 3.2. Also,
notice that the pattern applied in 3.2 != the one applied to my path, [^/]+. I am on 4.0.6.

Anyway, this pattern that Django is constructing and applying to my path also ‘helpfully’ adds \Z,
presumably as a terminus. Since Python uses the same escapes, that is turned into \Z. But, my guess
is that it is also prepending the raw string, (even though it does not show up in the
exception page - because that’s supposed to be good practice) with the result that the match
pattern fails because my path does not have literal \Z at the end.

Since I’d never seen \Z before, I did a lot of googling on this. I found two instances right here in
the forum of people with \Z in their patterns, but \Z was not discussed. So \Z has been around, but
I seem to be the only one it is messing with.

This is why I was hoping I could find it in the source and hack this behavior out of it, but I haven’t found it,

Suggestions?

I’m curious - what version of Python are you using, and what operating system are you running this on? What server are you running your code under?

Are you using any proxies or middleware that might be altering the WSGI object being sent in to Django?

It seems clear to me that something is non-standard here. Yes, Django appends \Z to the pattern if it is the last part of the URL. (\Z has the advantage over $ in a regex in that \Z matches the end of the string only. $ will match on the last character before a newline or the newline itself if it’s a multiline search. See re — Regular expression operations — Python 3.10.8 documentation for the details.

This means that if you are programmatically issuing a request on a URL, this could fail if you’re including a newline character in that url. (Browsers wouldn’t have this issue.)

Or, I guess you might also run into a problem if your slug contains a newline character, but I’m less sure about that. The slug itself would url encode the newline, but whatever is creating the link to it might not.

Just noticed something.

You have:

Which means that this URL requires two parameters, codekind and slug.

However, your error message shows:

Which shows you supplying a value for slug but not for codekind.

Where is your code / template that is trying to reverse this url?

I’m on Python 3.10. The last digit escapes me right now. I’m using Ubuntu … 22.04 lts? I’m on my phone and not at my computer.

Ok. I’ve landed at another stop on my run so I can reply to you.
Yes, both codekind and slug should be passed. From memory, the path is ‘/’.
But I’m pretty sure codekind is in there, because I used the debugger in Pycharm when this first started and that showed me that the value for codekind, coming straight from the url, was all lower case, but in my ChoiceField on the model it is title case. So I added a line to my view to take of that before creating the context.

What about hacking the source code that appends the \Z? I mentioned looking for it earlier. Do you know where I can find that?

That is what this article does, but it’s in Ruby:

https://docs.gitlab.com/ee/user/packages/container_registry/reduce_container_registry_storage.html

If you look you’ll see the line that says:
“\Z…is automatically added…”

I don’t have a proxy or any of that stuff. The server here is plain old runserver.

Can you help me find the source that adds the \Z?

You’re looking in the wrong place for the problem. There’s nothing incorrect or mistaken about these regex patterns being generated. You’ve got something else that you’re doing wrong in your code - either in your Django code or in how you’re accessing it.

You need to verify how you are producing these urls in your code and fix those problems.

I don’t think the \z is problematic. It doesn’t cause issues since it indicates the end of the line. If you want to find the code in Django, it’s from here.

You need to verify how you are producing these urls in your code and fix those problems.