nextai-translator/nextai-translator · error · Error

Invalid API Key

Error message

Invalid API Key

What it means

DeepSeek's listModels() maps HTTP 403 from the GET /models request to 'Invalid API Key' (capital K variant). 403 means the server recognized the request but refuses authorization — the credential is valid-shaped but lacks permission, is banned, or the account/region is restricted. Distinct from 401 ('Invalid API key').

Source

Thrown at src/common/engines/deepseek.ts:32

            return []
        }
        const url = urlJoin(apiURL, '/v1/models')
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`,
            },
        })
        if (response.status !== 200) {
            if (response.status === 401) {
                throw new Error('Invalid API key')
            }
            if (response.status === 404) {
                throw new Error('Invalid API URL')
            }
            if (response.status === 403) {
                throw new Error('Invalid API Key')
            }
            throw new Error(`Failed to list models: ${response.statusText}`)
        }
        const json = await response.json()
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        return json.data.map((model: any) => {
            return {
                id: model.id,
                name: model.id,
            }
        })
    }

    async getAPIModel(): Promise<string> {
        const settings = await getSettings()
        return settings.deepSeekAPIModel
    }
    async getAPIKey(): Promise<string> {

View on GitHub (pinned to f57537ee4a)

Solutions

  1. Check your DeepSeek account status and remaining balance on platform.deepseek.com
  2. Generate a brand-new API key (old one may be revoked) and update settings
  3. Disable VPN/proxy or switch egress region that may be blocked
  4. Retry from curl with the same key to see the 403 body for the exact reason

Example fix

// before
await deepseek.listModels(oldRevokedKey)
// after
const key = await promptUserForNewDeepSeekKey() // rotate after 403
await deepseek.listModels(key)
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call check can fully prevent a 403; verify account standing first.
const balance = await fetch('https://api.deepseek.com/user/balance', { headers: { Authorization: `Bearer ${apiKey}` } })
if (!balance.ok) throw new Error('Key or account not in good standing (would 403 on /models)')

Try / catch

try {
  const models = await deepseek.listModels(apiKey)
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid API Key') {
    // 403: key revoked/banned or region blocked — surface account-level guidance
    showAccountIssueHelp()
  } else { throw e }
}

Prevention

When it happens

Trigger: Calling DeepSeek.listModels(apiKey) when the API returns HTTP 403: the key is disabled/banned, the account has no balance or is region-blocked, or a WAF/CDN rule rejects the request origin.

Common situations: Account suspended for policy violation; negative balance after free credits ran out; calling from a blocked region/VPN egress IP; provider WAF flagging the extension's User-Agent; using a key from a closed beta that has been revoked.

Understand the failure class

Related errors


AI-assisted analysis of nextai-translator/nextai-translator@f57537ee4a (2026-08-31). Data as JSON: /api/errors/6ac061fa0c88b382. Report an issue: GitHub.