Common issues and solutions when using the DeepL CLI.
- Authentication Errors (Exit Code 2)
- Setup Wizard Issues (
deepl init) - Quota Errors (Exit Code 4)
- Rate Limiting (Exit Code 3)
- Network Errors (Exit Code 5)
- CheckFailed (Exit Code 8)
- Voice API Errors (Exit Code 9)
- Write API Issues
- Configuration Errors (Exit Code 7)
- Input Validation Errors (Exit Code 6)
- Cache Issues
- Document Translation Issues
- Glossary Issues
- Exit Codes Reference
- Environment Variables
- Getting More Help
- Still Having Issues?
Cause: The API key is missing, invalid, or expired.
Solutions:
-
Verify your key is set:
deepl auth show
- With a key configured:
API Key: XXXX...XXXX(shows first 4 and last 4 characters) - Without a key:
No API key set
- With a key configured:
-
Set or update your key:
echo "YOUR_API_KEY" | deepl auth set-key --from-stdin
-
Alternatively, use the environment variable:
export DEEPL_API_KEY="your-key-here"
-
Verify the key works:
deepl auth show
Notes:
- Free API keys end with
:fx. Pro keys do not. - The CLI auto-detects the API endpoint from the key suffix:
:fxkeys useapi-free.deepl.com, others useapi.deepl.com. Custom regional endpoints (e.g.api-jp.deepl.com) always take priority. - The stored config key takes precedence over the
DEEPL_API_KEYenvironment variable.
Cause: The deepl init wizard validates your API key by contacting the DeepL API. If the network is unreachable, validation will fail.
Solutions:
-
Check your internet connection and try again:
deepl init
-
If behind a proxy, set proxy environment variables before running init:
export HTTPS_PROXY=https://proxy.example.com:8443 deepl init
Cause: The key you entered is invalid, expired, or for a different API tier than expected.
Solutions:
-
Double-check your API key on the DeepL account page.
-
Ensure you're copying the full key, including the
:fxsuffix for free-tier keys. -
As a manual fallback, skip the wizard and pipe the key in:
echo "YOUR_API_KEY" | deepl auth set-key --from-stdin
Cause: Your DeepL account has reached its character translation limit.
Solutions:
-
Check your current usage:
deepl usage
-
For detailed breakdown:
deepl usage --format json
-
Wait for your quota to reset (monthly for most plans), or upgrade your DeepL plan.
Cause: Too many API requests in a short time period.
Solutions:
-
The CLI automatically retries rate-limited requests with exponential backoff. If you still see this error, reduce concurrency.
-
For batch/directory translation, the CLI uses concurrency control internally. Avoid running multiple CLI instances simultaneously on the same API key.
-
Retries honor the server's
Retry-Afterheader when present, falling back to full-jitter exponential backoff (max 3 retries by default; see the global--max-retriesflag). If errors persist, wait and try again.
Cause: Cannot reach the DeepL API servers.
Solutions:
-
Check your internet connection.
-
Verify DeepL API is reachable:
# Free keys (those ending in :fx) curl -s "https://api-free.deepl.com/v3/languages?resource=translate_text" -H "Authorization: DeepL-Auth-Key YOUR_KEY" # Pro keys — the free host answers a Pro key with 403, which is a reachable server curl -s "https://api.deepl.com/v3/languages?resource=translate_text" -H "Authorization: DeepL-Auth-Key YOUR_KEY"
-
If behind a corporate proxy, configure it via environment variables:
export HTTPS_PROXY=https://proxy.example.com:8443 # or export HTTP_PROXY=http://proxy.example.com:8080
-
The CLI retries idempotent requests on transient network errors automatically. Requests that submit work (translations, document uploads, glossary creation) are replayed only when the error proves the request never reached the server, so they are never double-billed — for those, rerun the command (exit code 5 is safe to retry at the script level).
Cause: The DeepL API is temporarily overloaded or undergoing maintenance.
Solutions:
-
Wait a few minutes and retry your request.
-
Use
--no-cacheto bypass any stale cached error responses:deepl translate "Hello" --to es --no-cache -
Read-only requests are retried automatically on 503. Requests that submit work (translate, document upload) surface the error immediately so they are never double-billed; retry them at the script level (exit code 5). If the error persists, the API may be experiencing an extended outage.
Cause: This is expected behavior, not an error. Exit code 8 means deepl write --check found improvements for your text.
Details:
- Exit 0 — Text is clean, no improvements suggested.
- Exit 8 — Improvements were found and suggested.
The same code is returned by deepl correct --check and by deepl sync validate, which exits 8 when it finds any error-severity issue (a lost placeholder, rewritten ICU structure, or a target file it could not read). Warnings alone leave sync validate at exit 0.
This exit code is useful in CI/CD pipelines or scripts to detect when text could be improved:
deepl write --check "Your text" --lang en-US
if [ $? -eq 8 ]; then
echo "Text has suggested improvements"
fiCause: Voice API requires a DeepL Pro account with Voice API access enabled.
Solutions:
- Verify your account has Voice API access on the DeepL website.
- Voice API uses the same endpoint resolution as other commands (
:fxkeys useapi-free.deepl.com). - Check that your audio file format is supported (OGG, Opus, WebM, MKA, FLAC, MP3, PCM).
Cause: The WebSocket URL returned by the API failed validation.
Notes:
- The CLI validates that streaming URLs use
wss://scheme and*.deepl.comhostnames. - This is a security check to prevent connection to unauthorized servers.
- If you see this error, it may indicate an API issue. Try again later.
If the CLI cannot auto-detect your audio format from the file extension, specify it explicitly:
deepl voice audio.raw --to de --content-type 'audio/pcm;encoding=s16le;rate=16000'Supported formats: audio/ogg, audio/webm, audio/flac, audio/mpeg, audio/x-matroska, and PCM variants.
Cause: The Write API supports fewer language pairs than the Translate API. Not all combinations are available.
Solutions:
-
Check which languages Write API supports:
deepl write --help
-
Use
--verboseto see the API request and response details:deepl write "Your text" --lang en-US --verbose -
If your language pair is unsupported, use the translate command as a fallback.
Cause: The requested --style or --tone may not be supported for the target language, or the text already matches it. deepl write has no --formality flag — formality is a deepl translate / deepl voice option; on Write, register is controlled by --style (simple, business, academic, casual, and their prefer_* forms) and --tone (enthusiastic, friendly, confident, diplomatic, and their prefer_* forms).
Solutions:
-
Check the accepted values:
deepl write --help
-
Use a
prefer_*value (e.g.--style prefer_business) so the API falls back rather than rejecting the request when the exact style is unavailable for that language. -
Use
--verboseto inspect the API response and confirm the style was applied.
Cause: The input text may already match the requested style, or the Write API determined no changes were needed.
Solutions:
-
Try a different style or formality level to see if changes are applied.
-
Use
--checkmode to compare the original with the improved version:deepl write "Your text" --lang en-US --check -
Check the verbose output for details:
deepl write "Your text" --lang en-US --verbose
Cause: The Write API has its own rate limits, separate from the Translate API.
Solutions:
-
The CLI automatically retries rate-limited requests with exponential backoff.
-
If processing multiple texts, consider adding delays between requests.
-
Check your current API usage:
deepl usage
Cause: The config file is corrupted or has invalid JSON.
The config file location depends on your setup (see Configuration Paths):
- XDG default:
~/.config/deepl-cli/config.json - Legacy:
~/.deepl-cli/config.json
Solutions:
-
View current config:
deepl config list
-
Overwrite a specific setting, or reset the whole config:
deepl config set <key> <value> deepl config reset # clears every stored setting; add --yes to skip the prompt
-
If the config file is corrupted, remove it and reconfigure:
rm ~/.config/deepl-cli/config.json # or ~/.deepl-cli/config.json echo "YOUR_API_KEY" | deepl auth set-key --from-stdin
-
Use a custom config directory:
export DEEPL_CONFIG_DIR=/path/to/config
Cause: deepl sync, deepl sync pull and deepl sync resolve take a per-project lock by writing .deepl-sync.lock.pidfile. A second invocation that finds a pidfile naming a live PID exits 7 rather than letting two runs overwrite each other's target files and lockfile.
Solutions:
-
Wait for the other run, or find it: the error names the PID and the time it started.
-
If that sync is definitely not running — a crashed run whose PID has been recycled — take the lock explicitly:
deepl sync --break-lock
Deleting
.deepl-sync.lock.pidfileby hand does the same thing. Both are unsafe if the sync really is running. -
A pidfile whose PID is simply gone is reclaimed automatically with a warning; no action needed.
See docs/SYNC.md — Concurrent sync for the full arbitration rules, and that guide's Troubleshooting section for sync-specific issues behind exit codes 10, 11 and 12.
Common causes and fixes:
-
translate: Requires text or file path and
--tolanguage:deepl translate "Hello" --to es -
watch: Requires a path and
--to:deepl watch ./docs --to es,fr
-
completion: Requires a shell name:
deepl completion bash
Use deepl languages to see all supported languages:
deepl languages --source
deepl languages --targetThe CLI exits 6 with a single line naming the required and the running version — requires Node.js >= 24.15.0, you are running v22.11.0. Upgrade Node.js to use the DeepL CLI.
Cause: The CLI requires Node.js 24.15.0 or later and checks the version at startup, before loading anything else, so an unsupported runtime gets that one line instead of an experimental-module warning or a later crash. The floor is a minor version because node:sqlite emits ExperimentalWarning on every earlier 24.x, including 24.0.0 — so a Node that satisfies "24 or later" is not necessarily enough.
Solution: upgrade Node.js — e.g. nvm install 24 && nvm use 24, or install Node 24 from nodejs.org; both give a current 24.x, which is past the floor. Confirm with node --version that the runtime invoking deepl is the upgraded one; a globally linked CLI can otherwise still run under an older default.
If you suspect cached translations are outdated:
# Clear the cache
deepl cache clear
# Check cache status
deepl cache statsIf the SQLite cache becomes corrupted:
# Disable cache temporarily
deepl cache disable
# Remove the cache file and re-enable
rm ~/.cache/deepl-cli/cache.db # or ~/.deepl-cli/cache.db for legacy installations
deepl cache enableCause: The cache uses Node's built-in node:sqlite module and the runtime could not load it. Running on Node.js older than 24.15.0 is reported earlier and separately — see Unsupported Node.js version — so what reaches this message is a runtime that reports a supported version but still has no usable node:sqlite: a Node built without SQLite support, or a non-Node runtime claiming a compatible version.
Translation and write commands keep working with caching disabled for the run; your cache database is not modified. deepl cache subcommands fail until the module loads.
Solution: run the CLI on an official Node.js build at 24.15.0 or later — e.g. nvm install 24 && nvm use 24, or install Node 24 from nodejs.org. To confirm the module is the problem, check that node -e "require('node:sqlite')" succeeds on the same runtime.
When translating a directory, you must specify --output:
deepl translate ./docs --to es --output ./docs-esSupported: PDF, DOCX, DOC, PPTX, XLSX, JPG, JPEG, PNG (document API); TXT, HTML, HTM, SRT, XLF, XLIFF (routed by size); MD (cached text API); JSON, YAML, YML (structured file API — string values extracted, translated, and reassembled). See docs/API.md for the per-format routing rules and size limits.
deepl translate document.docx --to fr --output translated.docx-
List available glossaries:
deepl glossary list
-
Glossary names are case-sensitive. Use the exact name or ID.
-
Glossaries are tied to specific language pairs. Ensure your source/target language matches the glossary's language pair.
| Code | Meaning | Retryable? |
|---|---|---|
| 0 | Success | N/A |
| 1 | General error | No |
| 2 | Authentication error | No |
| 3 | Rate limit exceeded | Yes |
| 4 | Quota exceeded | No |
| 5 | Network error | Yes |
| 6 | Invalid input | No |
| 7 | Configuration error | No |
| 8 | Check found issues (write --check, correct --check, sync validate) |
No |
| 9 | Voice API error | No |
| 10 | Sync drift detected (sync --frozen) | No |
| 11 | Sync lockfile conflict | No |
| 12 | Partial sync failure (some locales failed) | Yes (retry failed locales) |
Use exit codes in scripts for retry logic:
deepl translate "Hello" --to es
case $? in
0) echo "Success" ;;
3|5) echo "Transient error, retrying..." ;;
2) echo "Fix your API key" ;;
4) echo "Quota exceeded, wait for reset" ;;
*) echo "Error, check output" ;;
esac| Variable | Purpose |
|---|---|
DEEPL_API_KEY |
API key (fallback when no stored config key) |
DEEPL_CONFIG_DIR |
Override config and cache directory |
XDG_CONFIG_HOME |
Override XDG config base (default: ~/.config) |
XDG_CACHE_HOME |
Override XDG cache base (default: ~/.cache) |
HTTP_PROXY |
HTTP proxy URL |
HTTPS_PROXY |
HTTPS proxy URL (takes precedence over HTTP_PROXY) |
TMS_API_KEY |
API key for the configured TMS server (sync push/pull) |
TMS_TOKEN |
Alternative auth token for the configured TMS server |
NO_COLOR |
Disable colored output when set to any value |
FORCE_COLOR |
Force colored output (NO_COLOR wins if both are set) |
TERM |
TERM=dumb disables colored output and progress spinners |
# General help
deepl --help
# Command-specific help
deepl translate --help
deepl voice --help
deepl glossary --help
# Check CLI version
deepl --versionIf you encounter an issue not covered here, check the DeepL API documentation.
If your problem isn't listed above, file a bug report with:
- The command you ran
- The full error output
- Your CLI version (
deepl --version) - Your OS and Node.js version