Skip to content

Commit 8b9bc50

Browse files
committed
fix: add actionable suggestions for 400 Bad Request on issue list (CLI-BM, CLI-7B)
When the Sentry API returns 400 Bad Request for issue list queries, the error message shows the raw API detail but doesn't guide users on what to fix. This is the most common API error class, affecting 93 users across CLI-BM (55 users) and CLI-7B (38 users). Added a build400Detail() helper that enriches the 400 error detail with context-aware suggestions: - When --query is provided: link to Sentry search syntax docs - When using default --period (90d): suggest shorter time range - Always: suggest verifying project access The suggestions are appended after the original API detail so the specific error reason is still shown first.
1 parent a26e3f4 commit 8b9bc50

File tree

1 file changed

+61
-2
lines changed

1 file changed

+61
-2
lines changed

src/commands/issue/list.ts

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,58 @@ type ResolvedTargetsOptions = {
892892
setContext: (orgs: string[], projects: string[]) => void;
893893
};
894894

895+
/** Default --period value (used to detect user-implicit vs explicit). */
896+
const DEFAULT_PERIOD = "90d";
897+
898+
/**
899+
* Build an enriched error detail for 400 Bad Request responses.
900+
*
901+
* Appends actionable suggestions so users know what to try next. This is the
902+
* most common class of API error in `issue list` (CLI-BM, CLI-7B) — the Sentry
903+
* API rejects the request due to query syntax or parameter issues, but the raw
904+
* "400 Bad Request" message alone doesn't guide the user to a fix.
905+
*
906+
* @param originalDetail - The API response detail (may be undefined)
907+
* @param flags - Current command flags for context-aware hints
908+
* @returns Enhanced detail string with suggestions
909+
*/
910+
function build400Detail(
911+
originalDetail: string | undefined,
912+
flags: Pick<ListFlags, "query" | "period">
913+
): string {
914+
const parts: string[] = [];
915+
916+
if (originalDetail) {
917+
parts.push(originalDetail);
918+
}
919+
920+
const suggestions: string[] = [];
921+
922+
if (flags.query) {
923+
suggestions.push(
924+
"Check your --query syntax (Sentry search reference: https://docs.sentry.io/concepts/search/)"
925+
);
926+
}
927+
928+
if (!flags.period || flags.period === DEFAULT_PERIOD) {
929+
suggestions.push("Try a shorter time range: --period 14d or --period 24h");
930+
}
931+
932+
suggestions.push(
933+
"Verify you have access to the target project: sentry project list <org>/"
934+
);
935+
936+
if (suggestions.length > 0) {
937+
parts.push("");
938+
parts.push("Suggestions:");
939+
for (const s of suggestions) {
940+
parts.push(` • ${s}`);
941+
}
942+
}
943+
944+
return parts.join("\n");
945+
}
946+
895947
/**
896948
* Handle auto-detect, explicit, and project-search modes.
897949
*
@@ -1039,12 +1091,19 @@ async function handleResolvedTargets(
10391091
const { error: first } = failures[0]!;
10401092
const prefix = `Failed to fetch issues from ${targets.length} project(s)`;
10411093

1042-
// Propagate ApiError so telemetry sees the original status code
1094+
// Propagate ApiError so telemetry sees the original status code.
1095+
// For 400 errors, append actionable suggestions since the user's query
1096+
// or parameters are likely malformed. Common causes: invalid Sentry
1097+
// search syntax, unsupported period for the org's data retention.
10431098
if (first instanceof ApiError) {
1099+
const detail =
1100+
first.status === 400
1101+
? build400Detail(first.detail, flags)
1102+
: first.detail;
10441103
throw new ApiError(
10451104
`${prefix}: ${first.message}`,
10461105
first.status,
1047-
first.detail,
1106+
detail,
10481107
first.endpoint
10491108
);
10501109
}

0 commit comments

Comments
 (0)