diff --git a/packages/cli/src/lib/api/projects.ts b/packages/cli/src/lib/api/projects.ts index 65085d5e2..68dd36449 100644 --- a/packages/cli/src/lib/api/projects.ts +++ b/packages/cli/src/lib/api/projects.ts @@ -28,10 +28,13 @@ import { } from "../db/project-cache.js"; import { getCachedOrganizations } from "../db/regions.js"; import { type AuthGuardSuccess, withAuthGuard } from "../errors.js"; +import { logger } from "../logger.js"; import { getApiBaseUrl } from "../sentry-client.js"; import { buildProjectUrl } from "../sentry-urls.js"; import { isAllDigits } from "../utils.js"; +const log = logger.withTag("api.projects"); + import { API_MAX_PER_PAGE, apiRequestToRegion, @@ -77,8 +80,8 @@ export async function listProjects(orgSlug: string): Promise { const orgs = getCachedOrganizations(); const orgName = orgs.find((o) => o.slug === orgSlug)?.name ?? orgSlug; cacheProjectsForOrg(orgSlug, orgName, allResults); - } catch { - // Cache population is best-effort — never fail the command + } catch (error) { + log.debug(`Failed to cache projects for org '${orgSlug}'`, error); } return allResults; @@ -178,8 +181,8 @@ function seedProjectCaches( cacheProjectsForOrg(orgSlug, orgName, [ { id: project.id, slug: project.slug, name: project.name }, ]); - } catch { - // Best-effort — don't let cache failures break project creation + } catch (error) { + log.debug(`Failed to seed project cache for '${project.slug}'`, error); } if (dsn) { try { @@ -193,8 +196,8 @@ function seedProjectCaches( projectId: project.id, }); } - } catch { - // Best-effort — don't let cache failures break project creation + } catch (error) { + log.debug(`Failed to seed DSN key cache for '${project.slug}'`, error); } } } @@ -509,7 +512,8 @@ export async function findProjectByDsnKey( { params: { query: `dsn:${publicKey}` } } ); return data; - } catch { + } catch (error) { + log.debug(`DSN key lookup failed in region '${region.url}'`, error); return []; } }) @@ -631,7 +635,8 @@ export async function tryGetPrimaryDsn( const keys = await getProjectKeys(orgSlug, projectSlug); const activeKey = keys.find((k) => k.isActive); return activeKey?.dsn.public ?? keys[0]?.dsn.public ?? null; - } catch { + } catch (error) { + log.debug(`Failed to fetch DSN for '${orgSlug}/${projectSlug}'`, error); return null; } } diff --git a/packages/cli/src/lib/db/dsn-cache.ts b/packages/cli/src/lib/db/dsn-cache.ts index deb5cbdfc..1c1bc1858 100644 --- a/packages/cli/src/lib/db/dsn-cache.ts +++ b/packages/cli/src/lib/db/dsn-cache.ts @@ -147,6 +147,14 @@ export function getCachedDsn(directory: string): CachedDsnEntry | undefined { return; } + // Rows written by setCachedDetection() with an empty allDsns array store + // dsn="" and project_id="". Treat these as cache misses for the single-DSN + // path — callers expect a usable DSN when the result is defined. + if (!row.dsn) { + recordCacheHit("dsn", false); + return; + } + recordCacheHit("dsn", true); touchCacheEntry("dsn_cache", "directory", directory); return rowToCachedDsnEntry(row); diff --git a/packages/cli/src/lib/region.ts b/packages/cli/src/lib/region.ts index 4ac5fb536..ea9873f3e 100644 --- a/packages/cli/src/lib/region.ts +++ b/packages/cli/src/lib/region.ts @@ -10,9 +10,12 @@ import { getConfiguredSentryUrl } from "./constants.js"; import { getOrgByNumericId, getOrgRegion, setOrgRegion } from "./db/regions.js"; import { stripDsnOrgPrefix } from "./dsn/index.js"; import { withAuthGuard } from "./errors.js"; +import { logger } from "./logger.js"; import { getSdkConfig } from "./sentry-client.js"; import { getSentryBaseUrl, isSentrySaasUrl } from "./sentry-urls.js"; +const log = logger.withTag("region"); + /** * Promise cache for org region resolution, keyed by orgSlug. * @@ -181,9 +184,8 @@ export async function resolveEffectiveOrg(orgSlug: string): Promise { try { await resolveOrgRegion(orgSlug); return orgSlug; - } catch { - // Org not found or auth error — fall through to return the original - // slug. The downstream API call will produce a relevant error. + } catch (error) { + log.debug(`resolveOrgRegion failed for '${orgSlug}', using raw slug`, error); return orgSlug; } } @@ -193,7 +195,8 @@ export async function resolveEffectiveOrg(orgSlug: string): Promise { try { const { listOrganizationsUncached } = await import("./api-client.js"); await listOrganizationsUncached(); - } catch { + } catch (error) { + log.debug(`Failed to refresh org list for numeric ID '${orgSlug}'`, error); return orgSlug; }