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
- Go to platform.deepseek.com → API Keys, create a fresh key, and paste it into the DeepSeek settings without extra spaces
- Confirm you are using a DeepSeek key, not a key from another provider
- Check the API base URL in settings points to https://api.deepseek.com (a wrong URL can produce different status codes)
- 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
- Paste keys freshly and trimmed; never hand-truncate
- Rotate keys on the platform and update settings immediately
- Keep separate env vars per provider to avoid cross-pasting keys
- Probe /models with curl once after configuring a new key
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
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)