django/django · warning · Http404
Content type %(ct_id)s object %(obj_id)s doesn’t exist
Error message
Content type %(ct_id)s object %(obj_id)s doesn’t exist
What it means
Raised as Http404 by contenttypes shortcut() when looking up either the ContentType or the target object raises ObjectDoesNotExist, or when object_id cannot be parsed (ValueError), or fails validation (ValidationError). It signals that the (content_type_id, object_id) pair does not resolve to a real object.
Source
Thrown at django/contrib/contenttypes/views.py:23
from django.http import Http404, HttpResponseRedirect
from django.utils.translation import gettext as _
def shortcut(request, content_type_id, object_id):
"""
Redirect to an object's page based on a content-type ID and an object ID.
"""
# Look up the object, making sure it's got a get_absolute_url() function.
try:
content_type = ContentType.objects.get(pk=content_type_id)
if not content_type.model_class():
raise Http404(
_("Content type %(ct_id)s object has no associated model")
% {"ct_id": content_type_id}
)
obj = content_type.get_object_for_this_type(pk=object_id)
except (ObjectDoesNotExist, ValueError, ValidationError):
raise Http404(
_("Content type %(ct_id)s object %(obj_id)s doesn’t exist")
% {"ct_id": content_type_id, "obj_id": object_id}
)
try:
get_absolute_url = obj.get_absolute_url
except AttributeError:
raise Http404(
_("%(ct_name)s objects don’t have a get_absolute_url() method")
% {"ct_name": content_type.name}
)
absurl = get_absolute_url()
# Try to figure out the object's domain, so we can do a cross-site redirect
# if necessary.
# If the object actually defines a domain, we're done.
if absurl.startswith(("http://", "https://", "//")):View on GitHub (pinned to ae25a40be0)
Solutions
- Verify the object exists before emitting the shortcut URL in templates (use get_absolute_url only on real instances).
- Handle 404s in the frontend by re-fetching or hiding broken links.
- Ensure object_id values are valid integer pks (or match the model's pk type) before link generation.
- Run remove_stale_contenttypes if ContentType IDs are drifting.
Example fix
// before (template emits link to maybe-deleted object):
<a href="/r/{{ ct.id }}/{{ obj.id }}/">view</a>
// after (guard before rendering):
{% if obj %}<a href="{{ obj.get_absolute_url }}">view</a>{% endif %} Defensive patterns
Strategy: validation
Validate before calling
from django.contrib.contenttypes.models import ContentType
def resolve_or_none(ct_id, obj_id):
try:
ct = ContentType.objects.get(pk=ct_id)
if not ct.model_class():
return None
return ct.get_object_for_this_type(pk=obj_id)
except (ContentType.DoesNotExist, ValueError, Exception):
return None
obj = resolve_or_none(content_type_id, object_id)
if obj is None:
# render a graceful 'not found' instead of relying on Http404
... Try / catch
from django.http import Http404
try:
obj = ct.get_object_for_this_type(pk=object_id)
except (ObjectDoesNotExist, ValueError, ValidationError):
raise Http404('Resource not found') Prevention
- Validate object_id is the correct pk type before building shortcut URLs.
- Only render contenttype shortcut links for objects you have confirmed exist.
- Run remove_stale_contenttypes to keep ContentType IDs trustworthy.
When it happens
Trigger: A request to /r/<ct_id>/<obj_id>/ where ct_id has no ContentType, obj_id has no matching object, obj_id is non-numeric (ValueError on int pk), or a custom pk field fails ValidationError.
Common situations: Stale links/breadcrumbs/bookmarks pointing at deleted objects; templates rendering links before objects exist; user-tampered URLs with arbitrary IDs.
Related errors
- Content type %(ct_id)s object has no associated model
- %(ct_name)s objects don’t have a get_absolute_url() method
- Invalid geometry field.
- No feeds are registered.
- Slug %r isn’t registered.
AI-assisted analysis of django/django@ae25a40be0 (2026-08-06).
Data as JSON: /api/errors/f4f755f8abee5984.
Report an issue: GitHub.