Skip to content

Commit 3283be6

Browse files
committed
fix: improve error clarity and AuthError handling in cross-org event lookup
- resolveOrgAllTarget: throws a specific ContextError naming the org when the event is not found, instead of returning null and letting the caller emit a misleading "Organization and project is required" - findEventAcrossOrgs: two-pass approach — first return any successful match, then (only if none found) propagate AuthError. This avoids hiding auth errors when no org has the event, while not discarding a valid result just because another org had an auth error.
1 parent 3ec5c95 commit 3283be6

File tree

3 files changed

+20
-13
lines changed

3 files changed

+20
-13
lines changed

src/commands/event/view.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,22 @@ export async function resolveEventTarget(
209209
* Resolve target when only an org is known (e.g., from a Sentry event URL).
210210
* Uses the eventids endpoint to find the project directly.
211211
*
212-
* Returns null if the event is not found in the given org.
213-
* Propagates auth/network errors — if the user provided an explicit org
214-
* via URL, errors should surface rather than silently resolving a different org.
212+
* Throws a ContextError if the event is not found in the given org, with a
213+
* message that names the org so the error is not misleading.
214+
* Propagates auth/network errors from resolveEventInOrg.
215215
*/
216216
/** @internal Exported for testing */
217217
export async function resolveOrgAllTarget(
218218
org: string,
219219
eventId: string,
220220
_cwd: string
221-
): Promise<ResolvedEventTarget | null> {
221+
): Promise<ResolvedEventTarget> {
222222
const resolved = await resolveEventInOrg(org, eventId);
223223
if (!resolved) {
224-
return null;
224+
throw new ContextError(
225+
`Event ${eventId} in organization "${org}"`,
226+
`sentry event view ${org}/ ${eventId}`
227+
);
225228
}
226229
return {
227230
org: resolved.org,

src/lib/api-client.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,14 +1270,18 @@ export async function findEventAcrossOrgs(
12701270
orgs.map((org) => resolveEventInOrg(org.slug, eventId))
12711271
);
12721272

1273+
// First pass: return the first successful match
12731274
for (const result of results) {
12741275
if (result.status === "fulfilled" && result.value !== null) {
12751276
return result.value;
12761277
}
1277-
// Propagate auth errors immediately — they indicate a global problem
1278-
// (expired/missing token) rather than a per-org miss, so the user needs
1279-
// to know. Transient per-org failures (network, 5xx) are swallowed since
1280-
// other orgs may still succeed.
1278+
}
1279+
1280+
// Second pass (only reached when no org had the event): propagate
1281+
// AuthError since it indicates a global problem (expired/missing token).
1282+
// Transient per-org failures (network, 5xx) are swallowed — they are not
1283+
// global, and if the event existed in any accessible org it would have matched.
1284+
for (const result of results) {
12811285
if (result.status === "rejected" && result.reason instanceof AuthError) {
12821286
throw result.reason;
12831287
}

test/commands/event/view.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,12 +544,12 @@ describe("resolveOrgAllTarget", () => {
544544
expect(result?.prefetchedEvent?.eventID).toBe("abc123");
545545
});
546546

547-
test("returns null when event not found in explicit org", async () => {
547+
test("throws ContextError when event not found in explicit org", async () => {
548548
resolveEventInOrgSpy.mockResolvedValue(null);
549549

550-
const result = await resolveOrgAllTarget("acme", "notfound", "/tmp");
551-
552-
expect(result).toBeNull();
550+
await expect(
551+
resolveOrgAllTarget("acme", "notfound", "/tmp")
552+
).rejects.toBeInstanceOf(ContextError);
553553
});
554554

555555
test("propagates errors from resolveEventInOrg", async () => {

0 commit comments

Comments
 (0)