Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/sentry/features/temporary.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ def register_temporary_features(manager: FeatureManager) -> None:
manager.add("organizations:replay-ai-summaries-mobile", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable replay AI summaries for web replays
manager.add("organizations:replay-ai-summaries", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable reading replay details using EAP query
manager.add("organizations:replay-details-eap-query", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
# Enable version 2 of release serializer
manager.add("organizations:releases-serializer-v2", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable version 2 of reprocessing (completely distinct from v1)
Expand Down
29 changes: 20 additions & 9 deletions src/sentry/replays/endpoints/organization_replay_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def query_replay_instance_eap(
start: datetime,
end: datetime,
organization_id: int,
request_user_id: int,
request_user_id: int | None,
referrer: str = "replays.query.details_query",
):
select = [
Expand Down Expand Up @@ -159,14 +159,25 @@ def get(self, request: Request, organization: Organization, replay_id: str) -> R
projects = self.get_projects(request, organization, include_all_accessible=True)
project_ids = [project.id for project in projects]

snuba_response = query_replay_instance(
project_id=project_ids,
replay_id=replay_id,
start=filter_params["start"],
end=filter_params["end"],
organization=organization,
request_user_id=request.user.id,
)
# Use EAP query if feature flag is enabled
if features.has("organizations:replay-details-eap-query", organization):
snuba_response = query_replay_instance_eap(
project_ids=project_ids,
replay_ids=[replay_id],
start=filter_params["start"],
end=filter_params["end"],
organization_id=organization.id,
request_user_id=request.user.id,
)["data"]
Comment on lines +163 to +171
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Type mismatch in query_replay_instance_eap return value handling could cause TypeError if eap_read.query() returns a list directly.
Severity: MEDIUM | Confidence: 0.70

🔍 Detailed Analysis

The query_replay_instance_eap function assumes that eap_read.query() returns a dictionary containing a "data" key, which is then accessed as snuba_response = query_replay_instance_eap(...)["data"]. However, the non-EAP path, query_replay_instance, already unwraps the data by returning execute_query(...)["data"]. This inconsistency means that if eap_read.query() returns a list directly instead of a dictionary with a "data" key, accessing ["data"] will result in a TypeError at runtime when process_raw_response is called.

💡 Suggested Fix

Verify the return structure of eap_read.query() from src/sentry/replays/lib/eap/read.py. If it returns a list directly, modify line 171 to remove the ["data"] access.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/sentry/replays/endpoints/organization_replay_details.py#L163-L171

Potential issue: The `query_replay_instance_eap` function assumes that
`eap_read.query()` returns a dictionary containing a `"data"` key, which is then
accessed as `snuba_response = query_replay_instance_eap(...)["data"]`. However, the
non-EAP path, `query_replay_instance`, already unwraps the data by returning
`execute_query(...)["data"]`. This inconsistency means that if `eap_read.query()`
returns a list directly instead of a dictionary with a `"data"` key, accessing
`["data"]` will result in a `TypeError` at runtime when `process_raw_response` is
called.

Did we get this right? 👍 / 👎 to inform future reviews.

Reference_id: 2662889

else:
snuba_response = query_replay_instance(
project_id=project_ids,
replay_id=replay_id,
start=filter_params["start"],
end=filter_params["end"],
organization=organization,
request_user_id=request.user.id,
)

response = process_raw_response(
snuba_response,
Expand Down
Loading