Skip to content

Commit 2700cbc

Browse files
committed
fix(credentials): review round 3 — transient DNS and runtime host-error mapping
- EAI_AGAIN (temporary resolver failure) stays provider_unavailable; only ENOTFOUND maps to site_not_found - Token route surfaces site_not_found with its code (400) so runtime consumers can distinguish a dead stored host from bad credentials
1 parent 92a8a68 commit 2700cbc

2 files changed

Lines changed: 23 additions & 10 deletions

File tree

  • apps/sim

apps/sim/app/api/auth/oauth/token/route.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,26 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
188188
)
189189
} catch (error) {
190190
logger.error(`[${requestId}] Service account token error:`, error)
191-
// Classified provider outages are infra failures, not bad credentials.
192-
if (
193-
error instanceof TokenServiceAccountValidationError &&
194-
error.code === 'provider_unavailable'
195-
) {
196-
return NextResponse.json(
197-
{ error: 'Credential provider is temporarily unavailable' },
198-
{ status: 502 }
199-
)
191+
if (error instanceof TokenServiceAccountValidationError) {
192+
// Classified provider outages are infra failures, not bad credentials.
193+
if (error.code === 'provider_unavailable') {
194+
return NextResponse.json(
195+
{ error: 'Credential provider is temporarily unavailable' },
196+
{ status: 502 }
197+
)
198+
}
199+
// A stored host that no longer resolves is a configuration failure —
200+
// surface the code so runtime consumers can say "check the host"
201+
// instead of a generic auth error.
202+
if (error.code === 'site_not_found') {
203+
return NextResponse.json(
204+
{
205+
code: error.code,
206+
error: 'Credential host not found — reconnect the credential with a valid host',
207+
},
208+
{ status: 400 }
209+
)
210+
}
200211
}
201212
return NextResponse.json({ error: 'Failed to get service account token' }, { status: 401 })
202213
}

apps/sim/lib/credentials/token-service-accounts/errors.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ export async function fetchProvider(
6363
return await fetch(url, { ...init, signal: AbortSignal.timeout(PROVIDER_FETCH_TIMEOUT_MS) })
6464
} catch (error) {
6565
const causeCode = (error as { cause?: { code?: unknown } })?.cause?.code
66-
if (options?.dnsFailureCode && (causeCode === 'ENOTFOUND' || causeCode === 'EAI_AGAIN')) {
66+
// Only ENOTFOUND proves the host doesn't exist; EAI_AGAIN is a transient
67+
// resolver failure and stays provider_unavailable.
68+
if (options?.dnsFailureCode && causeCode === 'ENOTFOUND') {
6769
throw new TokenServiceAccountValidationError(options.dnsFailureCode, 400, {
6870
step,
6971
reason: options.dnsFailureReason ?? 'host does not resolve',

0 commit comments

Comments
 (0)