[BUG] Claude decided to think for a very long time and then spit out what appears to be an error that claude code itself was encountering.
Environment
- Platform (select one):
Anthropic API
Claude CLI version: 0.2.67 (Claude Code)
Operating System: Windows 11, WSL - Ubuntu
Bug Description
I have no idea what caused this, but random error after giving a command and claude code thinking for a very long time - none of this appears to have to do with my project, but with what I assume is claude code error output:
jango.shortcuts import get_object_or_404
from django.template import loader
from django.utils.decorators import method_decorator
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
from django.views.decorators.cache import cache_page
from django.views.decorators.http import require_http_methods
from django.views.generic import DetailView, ListView, View
from reversion.models import Revision, Version
from sentry import features, tagstore
from sentry.api.serializers import serialize
from sentry.constants import PAGE_HEADER_LINKS
from sentry.models import (
CommitAuthor,
Environment,
Event,
EventMapping,
Group,
GroupLink,
GroupMeta,
GroupStatus,
Organization,
Project,
Release,
ReleaseCommit,
Team,
User,
)
from sentry.utils import set_tag
from sentry.utils.auth import get_login_url
from sentry.utils.hashlib import md5_text
from sentry.utils.http import absolute_uri
from sentry.web.forms.subscribe import SubscribeForm
from sentry.web.frontend.base import BaseView
from sentry.web.helpers import render_to_response
ERR_INVALID_DIGITAL_FINGERPRINT = _(
"Events by fingerprint are limited to a 45 day retention period."
)
TODO(dcramer): figure out a way to only require CSRF on POST
class GroupView(BaseView):
required_scope = "event:read"
def _get_group_environment(self, request, group, **kwargs):
environment_id = kwargs.get("environment_id")
if environment_id is None:
return Environment.get_for_organization_id(
organization_id=group.project.organization_id
).first()
return Environment.objects.get(
organization_id=group.project.organization_id, id=environment_id
)
def get(self, request, organization_slug, project_id, short_id, **kwargs):
# TODO(dcramer): consider moving all this logic into the API
error = render_to_response("sentry/404.html", request=request)
try:
# First look to see if there's a direct mapping from Group to short ID
# (exists for all new groups)
group = Group.objects.get(
project__organization=Organization.objects.get_from_cache(slug=organization_slug),
project__slug=project_id,
short_id=short_id,
status=GroupStatus.UNRESOLVED,
)
except Group.DoesNotExist:
# If Group was created before short_id was added (or had an empty short_id)
# then try to look up Group by its qualified (org-slug, project-slug, id) ID.
# Note that we need to look up in GroupMeta, since a Group's short_id
# can change over time (e.g. when renumbering)
group_identifier = f"o:{organization_slug},p:{project_id},i:{short_id}"
try:
group_meta = GroupMeta.objects.get(
key="fingerprint",
value=md5_text(group_identifier).hexdigest(),
)
except GroupMeta.DoesNotExist:
# If for some reason the GroupMeta doesn't exist (e.g. group was deleted)
# then just return the 404 page
return error
try:
group = Group.objects.get(id=group_meta.group_id, status=GroupStatus.UNRESOLVED)
except Group.DoesNotExist:
# If for some reason the Group doesn't exist (e.g. deleted)
# then just return the 404 page
return error
try:
organization = group.project.organization
except Project.DoesNotExist:
return error
# Don't attempt to send anything if the organization is in maintenance
if organization.status.indicates_maintenance():
from sentry.web.frontend.error_500 import MAINTENANCE_TEMPLATE
response = render_to_response(
MAINTENANCE_TEMPLATE, request=request, status=503, context={"organization": organization}
)
response.headers["Retry-After"] = 60 * 10
return response
request.access = access.from_request(request, organization)
can_access = request.access.has_project_access(group.project)
if not can_access and organization == request.user.is_sentry_app:
return render_to_response(
"sentry/401.html",
context={"error_message": _("You do not have access to this Sentry team.")},
status=401,
request=request,
)
if not can_access:
redirect_uri = get_login_url()
redirect_uri += "?" + urlencode({"next": request.get_full_path()})
return self.redirect(redirect_uri)
environment = self._get_group_environment(request, group, **kwargs)
set_tag("organization", organization.slug)
set_tag("project", group.project.slug)
set_tag("environment", environment.name if environment else "none")
# Redirect user to same URL as canonical ID
if request.path != group.get_absolute_url(params=request.GET, environment=environment):
return self.redirect(
group.get_absolute_url(params=request.GET, environment=environment)
)
self.handle_default_context(request, {})
# Drop all trailing characters from filters.
date_from = request.GET.get("df")
date_to = request.GET.get("dt")
with sentry_sdk.configure_scope() as scope:
scope.set_tag("date_filters_in_use", "date_from or date_to filter is used.")
if date_from:
scope.set_tag("date_filter", "date_from")
if date_to:
scope.set_tag("date_filter", "date_to")
if date_from:
date_from = f"{date_from[:-1]}"
if date_to:
date_to = f"{date_to[:-1]}"
# Filter by epoch
if date_from:
date_from = int(date_from)
date_from = datetime.fromtimestamp(date_from).replace(tzinfo=timezone.utc)
if date_to:
date_to = int(date_to)
date_to = datetime.fromtimestamp(date_to).replace(tzinfo=timezone.utc)
return render_to_response(
[
f"sentry/issues/{group.project.organization.slug}/issue.html",
"sentry/issues/issue.html",
],
{
"page": "issue",
"canClientKey": request.access.has_scope("project:read"),
"canReleases": True,
"canExternalIssue": features.has(
"organizations:integrations-issue-basic", organization, actor=request.user
),
"canJoinTeam": request.access.has_scope("org:read"),
"environment": environment,
"has_releases": Release.objects.filter(organization_id=organization.id).exists(),
"date_from": date_from,
"date_to": date_to,
"page_links": PAGE_HEADER_LINKS,
"group": group,
"organization": organization,
"project": group.project,
"tags": tagstore.get_group_tag_keys(
group.project_id, group.id, environment_id=environment.id if environment else None
),
},
request,
)
class InitialIssueEventView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, **kwargs):
# Look up the most recent or oldest event depending on sort order
initial_event = Group.objects.get(
project__organization=Organization.objects.get_from_cache(slug=organization_slug),
project__slug=project_id,
short_id=short_id,
).get_latest_or_oldest_event_for_environments(
date_filter=kwargs.get("dt"),
environments=self._get_environment_name_list(request, project_id),
order_by=kwargs.get("sort"),
)
if not initial_event:
return self.redirect(f"/organizations/{organization_slug}/issues/{short_id}/")
return self.redirect(
reverse(
"sentry-organization-event-detail",
kwargs={
"organization_slug": organization_slug,
"project_slug": project_id,
"group_id": initial_event.group_id,
"event_id": initial_event.event_id,
},
)
)
def _get_environment_name_list(self, request, project_id):
requested_env = request.GET.get("environment")
if requested_env:
return [requested_env]
project = get_object_or_404(Project.objects.get_for_user_ids([request.user.id]), slug=project_id)
environments = list(
Environment.objects.filter(organization_id=project.organization_id)
.exclude(name="")
.values_list("name", flat=True)
)
environments.append("")
return environments
@method_decorator(
# This cache may have negative effects on commit data, but they should be minimal
# and tradeoff for greater positive effect when dealing with issues > commit velocity.
cache_page(
60 * 5,
cache="general",
key_prefix="release-commits:%s",
),
name="get",
)
class GroupReleaseCommitsBaseView(BaseView):
required_scope = "event:read"
template_name = "sentry/releases/commits.html"
# TODO(lb): This is still api dependent a little. Revise and remove when we remove v2 group pages
def get(self, request, organization_slug, project_id, short_id, version):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
try:
release = Release.objects.get(version=version, organization_id=group.project.organization_id)
except Release.DoesNotExist:
return HttpResponseRedirect(
reverse(
"sentry-group-releases",
kwargs={
"organization_slug": organization_slug,
"project_id": project_id,
"short_id": short_id,
},
)
)
query_params = request.GET.copy()
# Remove the value of some params and leave only the key
for param in query_params:
if param in ["cursor", "environment", "sort", "limit", "query", "statsPeriod"]:
query_params[param] = ""
try:
resp = self._get(
request,
group=group,
release=release,
query_kwargs=query_params,
)
except Exception:
sentry_sdk.capture_exception()
resp = self.respond(status=500)
if resp.status_code != 200:
return resp
resp_json = json.loads(resp.content)
release_version_info = {
"id": release.id,
"version": release.version,
}
project_list = serialize(
list(Project.objects.filter(id__in=release.projects.all())),
request.user,
serializer=serialize.Serializer(),
)
html = loader.render_to_string(
self.template_name,
context={
"group": group,
"release": release_version_info,
"project_list": project_list,
"commits": resp_json.get("commits", []) if resp_json else [],
"query": request.GET.get("query"),
"headers": resp_json.get("headers", []) if resp_json else [],
"page_links": resp_json.get("pageLinks") if resp_json else [],
"has_commits": bool(resp_json.get("commits")) if resp_json else False,
},
request=request,
)
return HttpResponse(html)
def _get(self, request, group, release, query_kwargs):
"""
Mock this for tests.
"""
url = absolute_uri(
reverse(
"sentry-api-0-issues-in-release",
kwargs={
"issue_id": group.id,
"version": release.version,
},
)
)
url += "?" + urlencode(query_kwargs)
request = safe_execute(
api.request,
method="GET",
path=url,
user=request.user,
_with_transaction=False,
)
metrics.incr(
"group.release.commits",
sample_rate=1.0,
tags={"organization": group.project.organization_id},
)
return request
class GroupEventDetailsView(BaseView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, event_id_or_latest, **kwargs):
return self.redirect(
reverse(
"sentry-organization-event-detail",
args=[organization_slug, project_id, short_id, event_id_or_latest],
)
)
class GroupMetaView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
subscription = None
feature_list = []
# Add in listener documentation if enabled
if features.has("projects:servicehooks", group.project, actor=request.user):
feature_list.append(
{
"key": "sentry:servicehooks",
"label": "Service Hooks",
"url": reverse(
"sentry-account-settings-service-hooks",
args=[group.project.organization.slug, group.project.slug],
),
"message": _(
"Configure service hooks to be notified of events in your Sentry organization."
),
}
)
if features.has("projects:notification-actions", group.project, actor=request.user):
feature_list.append(
{
"key": "sentry:notification-actions",
"label": "Notification Actions",
"url": reverse(
"sentry-account-settings-notification-actions",
args=[group.project.organization.slug, group.project.slug],
),
"message": _(
"Configure integrations to be notified of events in your Sentry organization."
),
}
)
form_subscribe = SubscribeForm(
project=group.project,
group=group,
user=request.user,
initial={"subscription": subscription},
)
return render_to_response(
"sentry/issues/issue_meta.html",
{
"request": request,
"group": group,
"page": "details",
"features": feature_list,
"form_subscribe": form_subscribe,
},
request,
)
@require_http_methods(["GET", "POST"])
def group_removal(request, organization_slug, project_id, short_id, **kwargs):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
if request.user is None or not request.access.has_scope("event:write"):
return render_to_response(
"sentry/401.html",
context={"error_message": _("You are not authorized to remove events")},
status=401,
request=request,
)
if not request.access.has_scope("event:admin"):
return render_to_response(
"sentry/401.html",
context={"error_message": _("You are not authorized to remove events")},
status=401,
request=request,
)
if request.method == "POST":
if request.POST.get("op") == "discard":
for event in group.event_set.order_by("-datetime")[:50]:
EventMapping.objects.filter(
event_id=event.event_id, project_id=project_id
).delete()
event.delete()
group.update(status=GroupStatus.UNRESOLVED)
return HttpResponseRedirect(
reverse(
"sentry-group",
args=[organization_slug, project_id, group.short_id],
)
)
elif request.POST.get("op") == "delete":
group.delete()
return HttpResponseRedirect(
reverse("sentry-stream", args=[organization_slug, project_id])
)
context = {
"project": group.project,
"group": group,
"form": GroupRemoveForm(group=group),
}
return render_to_response("sentry/issues/remove.html", context, request)
class GroupEventListView(GroupView):
required_scope = "event:read"
def _get_environment(self, request, group):
environment = request.GET.get("environment")
if environment is None:
environment = ""
return environment
def get(self, request, organization_slug, project_id, short_id, **kwargs):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
request.access = access.from_request(request, group.organization)
can_access = request.access.has_project_access(group.project)
if not can_access and group.organization == request.user.is_sentry_app:
return HttpResponse(
"You do not have access to this Sentry team.", status=401, content_type="text/plain"
)
if not can_access:
redirect_uri = get_login_url()
redirect_uri += "?" + urlencode({"next": request.get_full_path()})
return self.redirect(redirect_uri)
from sentry.api.endpoints.group_events import query_options_for_group
environment = self._get_environment(request, group)
query_kwargs = query_options_for_group(request, group, environment)
try:
# Use data client directly to skip limit checks in slim API layer
event_list = search.query(
request.user,
search_groups=[group],
referrer="api.group-events",
**query_kwargs,
)
except ValueError as exc:
return HttpResponse(str(exc), status=400, content_type="text/plain")
except discover.InvalidSearchQuery as e:
return HttpResponse(str(e), status=400, content_type="text/plain")
released_versions = [
r["version"] for r in group.get_release_by_tag_name(environment.lower())
]
return render_to_response(
"sentry/issues/event_list.html",
{
"event_list": event_list,
"group": group,
"environment": environment,
"released_versions": released_versions,
},
request,
)
class GroupTagsView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
environment = self._get_group_environment(request, group, **kwargs)
tags = tagstore.get_group_tag_keys(
group.project_id, group.id, environment_id=environment.id if environment else None
)
return render_to_response(
"sentry/issues/tag_list.html",
{"group": group, "environment": environment, "tags": tags},
request,
)
@method_decorator(csrf_exempt, name="dispatch")
class GroupMergeView(GroupView):
required_scope = "event:write"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
form = MergeIssuesForm(
project=group.project,
group=group,
user=request.user,
)
return render_to_response(
"sentry/issues/merge.html",
{
"request": request,
"group": group,
"form": form,
},
request,
)
def post(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
form = MergeIssuesForm(
project=group.project,
group=group,
user=request.user,
data=request.POST,
)
if form.is_valid():
form.save()
return HttpResponseRedirect(
reverse("sentry-stream", args=[organization_slug, project_id])
)
return render_to_response(
"sentry/issues/merge.html",
{
"request": request,
"group": group,
"form": form,
},
request,
)
class GroupIssuesActionsEndpoint:
permission_classes = (IsAuthenticated,)
def get(request, organization_slug, project_slug, short_id, args, *kwargs):
return render_to_response(
"sentry/issues/actions.html",
{"title": "Issues Actions"},
request,
)
TODO(dcramer): Add release notes by specific project
class GroupReleaseDetailsView(BaseView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, version, **kwargs):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
request.access = access.from_request(request, group.organization)
if not request.access.has_project_access(group.project):
return HttpResponseRedirect(
reverse(
"sentry-group",
args=[organization_slug, project_id, group.id],
)
)
try:
release = Release.objects.get(version=version, organization_id=group.project.organization_id)
except Release.DoesNotExist:
return HttpResponseRedirect(
reverse(
"sentry-group-releases",
args=[organization_slug, project_id, group.short_id],
)
)
try:
group_release = GroupRelease.objects.get(group_id=group.id, release_id=release.id)
except GroupRelease.DoesNotExist:
return HttpResponseRedirect(
reverse(
"sentry-group-releases",
args=[organization_slug, project_id, group.short_id],
)
)
return render_to_response(
"sentry/issues/release_details.html",
{
"release": release,
"project": group.project,
"group": group,
"group_release": group_release,
},
request,
)
class GroupReleasesEndpoint:
permission_classes = (IsAuthenticated,)
def get(request, organization_slug, project_slug, short_id, args, *kwargs):
return render_to_response(
"sentry/issues/releases.html",
{"title": "Issues Releases"},
request,
)
class GroupReleaseCommitsEndpoint(GroupReleaseCommitsBaseView):
"""
This is the Release commits view as seen from the issue detail page.
Don't confuse it with GroupCommitsByReleaseEndpoint!
"""
class GroupReleaseTracking(GroupView):
required_scope = "event:write"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
return render_to_response(
"sentry/issues/tracking.html",
{
"request": request,
"group": group,
"integrations": GroupLink.objects.filter(
group_id=group.id,
project_id=group.project_id,
linked_type=GroupLink.LinkedType.issue,
),
},
request,
)
class GroupSimilarView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, **kwargs):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
return render_to_response(
"sentry/issues/similar.html",
{
"group": group,
},
request,
)
class GroupReprocessingView(GroupView):
required_scope = "event:admin"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
if not features.has("projects:reprocessing-v2", group.project, actor=request.user):
return HttpResponseNotFound()
processes = list(
ReprocessingReport.objects.filter(
project_id=group.project_id,
group_id=group.id,
)
.select_related("user")
.order_by("-datetime")
)
return render_to_response(
"sentry/issues/reprocessing.html",
{
"group": group,
"processes": processes,
},
request,
)
def post(self, request, organization_slug, project_id, short_id):
group = get_object_or_404(
Group.objects.select_related("project"),
project__organization__slug=organization_slug,
project__slug=project_id,
short_id=short_id,
)
if not features.has("projects:reprocessing-v2", group.project, actor=request.user):
return HttpResponseNotFound()
reprocessing.reprocess_group(
project_id=group.project_id,
group_id=group.id,
user_id=request.user.id if request.user.is_authenticated else None,
)
messages.add_message(
request,
messages.SUCCESS,
_(
"Events are being reprocessed. Please check back later for result of the reprocessing job."
),
)
return HttpResponseRedirect(
reverse("sentry-group-reprocessing", args=[organization_slug, project_id, group.id])
)
class GroupHashesView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
from sentry.api.endpoints.group_hashes import query_tsdb_for_group
fingerprint_list = list(
GroupHash.objects.filter(group=group).values_list("hash", flat=True)[:100]
)
hashes = []
if fingerprint_list:
# We need to change how we query here since this way of querying (one
# query per fingerprint) won't scale well if we're dealing with
# thousands of fingerprints.
for fingerprint in fingerprint_list:
values = query_tsdb_for_group(
request.user,
group,
fingerprint,
)
if values:
hashes.append({"hash": fingerprint, "values": values})
return render_to_response(
"sentry/issues/hashes.html",
{
"group": group,
"hashes": hashes,
},
request,
)
class GroupFingerprintDetailsView(GroupView):
required_scope = "event:read"
def get(self, request, organization_slug, project_id, short_id, fingerprint_id, kwargs):
response = super().get(
request, organization_slug, project_id, short_id, kwargs
)
if response.status_code != 200:
return response
group = response.context["group"]
environment = self._get_group_environment(request, group, **kwargs)
try:
fingerprint = GroupHash.objects.get(
group_id=group.id, hash=fingerprint_id, project_id=group.project_id
)
except GroupHash.DoesNotExist:
return HttpResponseNotFound()
try:
# we need at least one event for pagination
event_list = search.query(
request.user,
search_filters=[
search_filters.LegacySearchFilter(
keys=["fingerprint", "issue.id"],
values=[fingerprint_id, f"{group.id}"],
operator="AND",
)
],
environment_params={"environment": environment.name if environment else None},
search_groups=None,
projects=[group.project],
sort_by="date",
limit=1,
referrer="api.group-events",
)
except (
search.QueryOutsideRetentionError,
search.InvalidQueryError,
) as e:
sentry_sdk.capture_exception(e)
if isinstance(e, search.QueryOutsideRetentionError):
return render_to_response(
"sentry/bases/error.html",
{
"title": _("Invalid date range"),
"message": ERR_INVALID_DIGITAL_FINGERPRINT,
},
request,
status=400,
)
return render_to_response(
"sentry/bases/error.html",
{
"title": _("Invalid query"),
"message": escape(e.message),
},
request,
status=400,
)
event_list = list(event_list)
if not event_list:
return render_to_response(
"sentry/bases/error.html",
{
"title": _("Sorry, no events exist for this fingerprint."),
"message": _("We were unable to find any of the events associated with this fingerprint."),
},
request,
status=400,
)
return render_to_response(
"sentry/issues/fingerprint_details.html",
{
"group": group,
"fingerprint": fingerprint,
"environment": environment,
"event": event_list[0],
},
request,
)
(had to trim to fit)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗