From acf4bd70fb38b16fd2dff7790f2f3c2122e0251a Mon Sep 17 00:00:00 2001 From: Ryan Ghadimi Date: Wed, 14 Jan 2026 17:01:59 +0000 Subject: [PATCH] Add handling for 429s from cache service --- .../src/internal/shared/cacheTwirpClient.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/cache/src/internal/shared/cacheTwirpClient.ts b/packages/cache/src/internal/shared/cacheTwirpClient.ts index f6c2af61..ade1b8c9 100644 --- a/packages/cache/src/internal/shared/cacheTwirpClient.ts +++ b/packages/cache/src/internal/shared/cacheTwirpClient.ts @@ -1,4 +1,4 @@ -import {info, debug} from '@actions/core' +import {info, debug, warning} from '@actions/core' import {getUserAgentString} from './user-agent' import {NetworkError, UsageError} from './errors' import {getCacheServiceURL} from '../config' @@ -109,6 +109,20 @@ class CacheServiceClient implements Rpc { errorMessage = `${errorMessage}: ${body.msg}` } + + // Handle rate limiting - don't retry, just warn and exit + if (statusCode === HttpCodes.TooManyRequests) { + const retryAfterHeader = response.message.headers['retry-after'] + if (retryAfterHeader) { + const parsedSeconds = parseInt(retryAfterHeader, 10) + if (!isNaN(parsedSeconds) && parsedSeconds > 0) { + warning( + `You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds` + ) + } + } + throw new Error(`Rate limited: ${errorMessage}`) + } } catch (error) { if (error instanceof SyntaxError) { debug(`Raw Body: ${rawBody}`) @@ -162,8 +176,7 @@ class CacheServiceClient implements Rpc { HttpCodes.BadGateway, HttpCodes.GatewayTimeout, HttpCodes.InternalServerError, - HttpCodes.ServiceUnavailable, - HttpCodes.TooManyRequests + HttpCodes.ServiceUnavailable ] return retryableStatusCodes.includes(statusCode)