Skip to content

Commit d5e43f6

Browse files
committed
fix: retry on error_code 161
1 parent c01837e commit d5e43f6

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

lib/core/concurrency-queue.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,11 @@ export function ConcurrencyQueue ({ axios, config, plugins = [] }) {
494494
return Promise.reject(responseHandler(err))
495495
}
496496
} else if ((response.status === 401 && this.config.refreshToken)) {
497-
// If error_code is 294 (2FA required), don't retry/refresh - pass through the error as-is
497+
// Retry/refresh only for authentication-related 401s (e.g. token expiry). Do not retry
498+
// when the API returns a specific error_code for non-auth issues (2FA, permission, etc.).
498499
const apiErrorCode = response.data?.error_code
499-
if (apiErrorCode === 294) {
500+
const NON_AUTH_401_ERROR_CODES = new Set([294, 161]) // 294 = 2FA required, 161 = env/permission
501+
if (apiErrorCode !== undefined && apiErrorCode !== null && NON_AUTH_401_ERROR_CODES.has(apiErrorCode)) {
500502
const err = runPluginOnResponseForError(error)
501503
return Promise.reject(responseHandler(err))
502504
}

test/unit/concurrency-Queue-test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,40 @@ describe('Concurrency queue test', () => {
639639
})
640640
.catch(done)
641641
})
642+
643+
it('should not refresh token when error_code is 161 (env/permission) with 401 status', done => {
644+
let refreshTokenCallCount = 0
645+
const refreshTokenStub = sinon.stub().callsFake(() => {
646+
refreshTokenCallCount++
647+
return Promise.resolve({ authorization: 'Bearer new_token' })
648+
})
649+
650+
const axiosWithRefresh = client({
651+
baseURL: `${host}:${port}`,
652+
authorization: 'Bearer <token_value>',
653+
refreshToken: refreshTokenStub
654+
})
655+
656+
const mock = new MockAdapter(axiosWithRefresh.axiosInstance)
657+
mock.onGet('/test161').reply(401, {
658+
error_message: "Environment doesn't exists or insufficient permission to access it.",
659+
error_code: 161
660+
})
661+
662+
axiosWithRefresh.axiosInstance.get('/test161')
663+
.then(() => {
664+
done(new Error('Expected error was not thrown'))
665+
})
666+
.catch((error) => {
667+
expect(refreshTokenCallCount).to.equal(0)
668+
expect(refreshTokenStub.called).to.equal(false)
669+
expect(error.response.status).to.equal(401)
670+
expect(error.response.data.error_code).to.equal(161)
671+
expect(error.response.data.error_message).to.include("Environment doesn't exists or insufficient permission")
672+
done()
673+
})
674+
.catch(done)
675+
})
642676
})
643677

644678
function makeConcurrencyQueue (config) {

0 commit comments

Comments
 (0)