nextai-translator/nextai-translator · error · Error

Invalid API key

Error message

Invalid API key

What it means

DeepSeek's listModels() checks the GET /models response status and maps 401 to 'Invalid API key'. This means the DeepSeek server rejected the Bearer token supplied in the Authorization header. It is a deliberate, specific mapping so users know the credential — not the network — is the problem.

Solutions

  1. Go to platform.deepseek.com → API Keys, create a fresh key, and paste it into the DeepSeek settings without extra spaces
  2. Confirm you are using a DeepSeek key, not a key from another provider
  3. Check the API base URL in settings points to https://api.deepseek.com (a wrong URL can produce different status codes)
  4. Retry the model list after saving the new key

Example fix

// before
const key = process.env.DEEPSEEK_KEY!.trim().slice(0, 40) // truncated!
await deepseek.listModels(key)
// after
const key = process.env.DEEPSEEK_KEY?.trim()
if (!key) throw new Error('DEEPSEEK_KEY is not set')
await deepseek.listModels(key)
Defensive patterns

Strategy: validation

Validate before calling

const key = apiKey?.trim()
if (!key || !key.startsWith('sk-')) {
  throw new Error('DeepSeek API key missing or malformed (expected sk-...)')
}

Type guard

function isDeepSeekKey(k: unknown): k is string {
  return typeof k === 'string' && /^sk-\S{20,}$/.test(k.trim())
}

Try / catch

try {
  const models = await deepseek.listModels(apiKey)
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid API key') {
    openSettings('DeepSeek API key rejected — generate a new one at platform.deepseek.com')
  } else { throw e }
}

Prevention

When it happens

Trigger: Calling DeepSeek.listModels(apiKey) when the API returns HTTP 401: the apiKey is undefined/wrong/revoked, contains whitespace or a truncated copy-paste, or the key was created for a different service (e.g. OpenAI key pasted into DeepSeek settings).

Common situations: Copy-pasting the key with surrounding spaces; regenerating the key on platform.deepseek.com and not updating the app settings; using an old free-credit key after it expired; mixing up providers when configuring multiple engines.

Understand the failure class

Related errors


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

Appendix: source

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

        let apiKey = apiKey_
        if (!apiKey) {
            apiKey = await this.getAPIKey()
        }
        const apiURL = await this.getAPIURL()
        if (!apiKey || !apiURL) {
            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,
            }
        })
    }

View on GitHub (pinned to f57537ee4a)