Sửa lỗi Claude Code báo API key không hợp lệ
Claude Code báo “invalid API key” dù bạn có subscription? Tìm ANTHROPIC_API_KEY còn sót trên VPS và hiểu vì sao /login không sửa được lỗi này.
Vì sao Claude Code báo lỗi API key không hợp lệ
Claude Code báo Invalid API key vì 2 nguyên nhân khác nhau, và cách sửa của hai nguyên nhân này là ngược nhau. Có thể bạn định xác thực bằng API key nhưng key đó sai, đã bị thu hồi hoặc thuộc tài khoản khác. Cũng có thể bạn không hề định dùng key, nhưng một ANTHROPIC_API_KEY còn sót lại trong môi trường của server đang được ưu tiên hơn subscription mà bạn đã đăng nhập. Theo tài liệu của Anthropic tại thời điểm tháng 10 năm 2026, trường hợp thứ hai được nêu rõ: sau khi bạn chấp nhận một key được đặt trong environment, key đó sẽ được dùng thay cho subscription Claude Pro, Max, Team hoặc Enterprise, ngay cả khi bạn đã đăng nhập; với claude -p, key luôn được dùng khi có mặt.
Hãy xác định bạn đang ở nhánh nào trước khi thay đổi bất kỳ thứ gì. Khởi động Claude Code và chạy /status. Tài liệu mô tả một dòng Login method hiển thị tài khoản subscription của bạn, và một dòng API key xuất hiện khi API key đang được dùng. Nếu bạn thấy dòng API key trên một máy mà trước đó bạn chỉ chạy /login, thì vấn đề nằm ở environment; xác thực lại sẽ không thay đổi environment đó.
Mọi nội dung bên dưới đều là command để bạn chạy trên server của mình. Hãy đọc output trước khi thực hiện bước tiếp theo.
Thứ tự credential và lý do /login không có tác dụng
Khi có nhiều credential, Claude Code chọn theo thứ tự đã được tài liệu hóa:
- Credential của cloud provider khi đã đặt
CLAUDE_CODE_USE_BEDROCK,CLAUDE_CODE_USE_VERTEXhoặcCLAUDE_CODE_USE_FOUNDRY. - Biến
ANTHROPIC_AUTH_TOKEN, được gửi dưới dạng headerAuthorization: Bearer. - Biến
ANTHROPIC_API_KEY, được gửi dưới dạng headerX-Api-Key. - Output của một script
apiKeyHelper. - Biến
CLAUDE_CODE_OAUTH_TOKEN, chứa token từclaude setup-token. - Credential của profile Anthropic và federation.
- Credential OAuth của subscription do
/loginghi.
Đọc danh sách này từ dưới lên. /login ghi credential ở vị trí cuối cùng. Trên Linux, credential này nằm trong ~/.claude/.credentials.json với file mode 0600. Mọi credential trong environment ở phía trên đều được ưu tiên hơn nó, kể cả API key ngay khi API key được chấp thuận. Vì vậy, một lần đăng nhập mới chỉ refresh credential mà session không bao giờ dùng: login thành công nhưng không giải quyết được vấn đề. Đó là toàn bộ lý do cách sửa dễ thấy này không có tác dụng.
Interactive session có thêm một bước khiến nhiều người nhầm lẫn. Tài liệu cho biết bạn sẽ được hỏi một lần để chấp thuận hoặc từ chối API key tìm thấy trong environment, và lựa chọn này được ghi nhớ. Nếu bạn đã chấp thuận từ vài tháng trước, lựa chọn đó vẫn còn hiệu lực và key tiếp tục được ưu tiên hơn login. Nếu bạn đã từ chối, key sẽ bị bỏ qua mà không hỏi lại. Khi đó sẽ xuất hiện vấn đề ngược lại: biến đã được đặt, env hiển thị biến đó, nhưng session không sử dụng nó. Bạn có thể thay đổi lựa chọn bằng toggle "Use custom API key" trong /config. Toggle này chỉ xuất hiện khi ANTHROPIC_API_KEY được đặt trong environment. Ở chế độ non-interactive, tức claude -p trong script hoặc cron job, sẽ không có prompt: khi có key, key luôn được sử dụng.
Làm thế nào để tìm ANTHROPIC_API_KEY bị sót trên một VPS?
Trước tiên, xác nhận biến này tồn tại trong shell mà bạn dùng để khởi động Claude Code.
env | grep -i anthropicSau đó chạy cách khắc phục trên trang troubleshooting của Anthropic. Lệnh này cũng dùng để kiểm tra nguyên nhân:
unset ANTHROPIC_API_KEY
claudeNếu Claude Code khởi động và /status hiện subscription của bạn, nguyên nhân đã được xác nhận. Biến này sẽ xuất hiện lại trong shell tiếp theo, vì unset chỉ thay đổi shell mà bạn đã nhập lệnh. Phần còn lại của mục này tập trung vào việc tìm nơi thiết lập biến đó.
Shell profile và file environment trên toàn hệ thống
grep -rn ANTHROPIC ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc \
~/.config/fish/config.fish /etc/environment /etc/profile /etc/profile.d/ 2>/dev/nullTrang của Anthropic nêu ~/.zshrc, ~/.bashrc và ~/.profile. Trên server, hãy mở rộng phạm vi tìm kiếm. /etc/environment được PAM (pluggable authentication modules) đọc khi mọi user trên máy đăng nhập. Vì vậy, key do đồng nghiệp thiết lập có thể xuất hiện trong session của bạn. Các file trong /etc/profile.d/ được chạy bởi login shell. Lưu ý rằng .bashrc chỉ được shell tương tác đọc, nên file này không thể giải thích lỗi bên trong systemd service. File cần kiểm tra phụ thuộc vào cách Claude Code được khởi động.
systemd unit
Unit không đọc shell profile của bạn. Environment của unit lấy từ các dòng Environment= và EnvironmentFile= trong unit cùng mọi drop-in.
systemctl cat claude-agent.service
systemctl show -p Environment claude-agent.servicesystemctl cat in ra unit file, sau đó là mọi drop-in từ /etc/systemd/system/claude-agent.service.d/. Override thường nằm ở đó. systemctl show -p Environment in ra environment mà systemd thực sự sẽ truyền cho process. Với service chạy dưới user của bạn, thêm --user vào cả hai lệnh. Sau khi sửa unit, chạy sudo systemctl daemon-reload rồi restart service, vì environment được tạo khi process khởi động và process đang chạy vẫn giữ bản sao đã được truyền cho nó.
Session tmux và screen vẫn còn sau khi bạn sửa cấu hình
Đây là nguyên nhân khiến nhiều người mất hàng giờ. tmux server giữ environment tại thời điểm nó được khởi động. Pane mới kế thừa environment từ server, không phải từ shell hiện tại của bạn. Bạn xóa export khỏi .bashrc, mở pane mới, nhưng key cũ vẫn còn.
tmux show-environment | grep -i ANTHROPIC
tmux set-environment -r ANTHROPIC_API_KEYset-environment -r đánh dấu tên biến cần xóa khỏi environment mà tmux truyền cho process mới. Thêm -g cũng thực hiện việc tương tự với global environment của server. Các pane đã mở vẫn giữ bản sao riêng, vì environment của process chỉ có thể thay đổi từ bên trong process đó. Sau khi xóa export, cách đáng tin cậy là detach, chạy tmux kill-server rồi khởi động session mới. screen cũng hoạt động tương tự. Bạn nên biết điều này trước khi thiết lập session Claude Code chạy lâu trong tmux trên VPS, vì session đó chính là loại process có thể tồn tại qua ba lần sửa cấu hình.
Để đọc environment của một process đang chạy, hãy yêu cầu kernel cung cấp:
tr '\0' '\n' < /proc/$(pgrep -n claude)/environ | grep -i anthropicLệnh này in ra các giá trị được truyền cho process tại thời điểm exec. Đây là các giá trị process thực sự đang dùng. Bạn phải là process owner hoặc root mới đọc được file đó. pgrep -n claude chọn kết quả khớp mới nhất, nên hãy kiểm tra PID nếu có nhiều process đang chạy.
Docker và Compose
docker exec claude-agent env | grep -i anthropic
docker compose configLệnh đầu tiên hiển thị environment bên trong container đang chạy, bao gồm các giá trị từ --env-file, block environment: hoặc dòng ENV đã được tích hợp vào image. docker compose config in ra compose file sau khi resolve các biến, nên bạn thấy giá trị thực tế sẽ được truyền thay vì placeholder ${ANTHROPIC_API_KEY} đã viết. Cả hai lệnh đều in secret ra terminal, vì vậy hãy chạy chúng trong session mà bạn sẵn sàng xóa lịch sử hoặc làm sạch output. Compose cũng tự động load file .env nằm cạnh compose file mà không cần chỉ định. Đây thường là nơi chứa key mà không ai nhớ đã thêm.
File settings vẫn tồn tại sau mọi lần sửa shell
File settings của Claude Code chứa block env. Tài liệu nêu rõ cơ chế xung đột: khi cùng một biến được thiết lập trong shell và trong block env của file settings, giá trị trong file settings thường được áp dụng. Ngoại lệ là session được khởi động bởi ứng dụng Claude Desktop hoặc self-hosted environment runner, trong đó environment lúc khởi động được ưu tiên. Với claude được khởi động trong terminal trên server, key được ghi trong đó sẽ có hiệu lực cao hơn mọi unset mà bạn nhập.
grep -rn ANTHROPIC ~/.claude/settings.json .claude/settings.json .claude/settings.local.json 2>/dev/nullHãy kiểm tra cả file của project và file của user. .claude/settings.json thường được commit nên được chia sẻ với mọi người clone repository. Tổ chức cũng có thể đẩy managed settings, và các settings này có ưu tiên cao hơn file của bạn. Nếu tìm thấy key mà bạn không thể xóa, hãy hỏi người quản lý các settings đó.
Nhánh còn lại: key thực sự sai
Nếu /status hiển thị một API key và bạn đúng là muốn dùng key đó, hãy hiểu lỗi đúng theo nội dung của nó. Tài liệu tham chiếu lỗi của Anthropic cho biết Invalid API key · Fix external API key có nghĩa là API đã từ chối key lấy từ ANTHROPIC_API_KEY hoặc một script apiKeyHelper, hoặc Claude Code đã chặn key trước khi gửi. Các điểm cần kiểm tra cho lỗi này:
- Kiểm tra xem key có bị gõ sai không.
- Xác nhận trong Console rằng key chưa bị thu hồi.
- Đảm bảo một công cụ như direnv, dotenv shell plugin hoặc terminal của IDE không nạp một key cũ từ file
.envcủa project.
Kiểm tra giá trị mà không in nó vào scrollback:
echo "len=${#ANTHROPIC_API_KEY} tail=${ANTHROPIC_API_KEY: -6}"Độ dài dài hơn dự kiến một hoặc hai ký tự thường có nghĩa là newline ở cuối hoặc dấu ngoặc kép đã đi kèm khi copy và paste, hoặc file key được lưu bằng line ending của Windows đã để lại một carriage return mà $(cat keyfile) không loại bỏ. Các phiên bản hiện tại phát hiện những ký tự mà header không thể chứa trước khi gửi: khi thông báo tiếp tục sau Fix external API key với mô tả như Invalid X-Api-Key header value from ANTHROPIC_API_KEY: it contains a line break, Claude Code đã dừng request và API chưa bao giờ nhận được key. Một dấu ngoặc kép thừa là ký tự header hợp lệ, nên nó được gửi đi như một phần của header X-Api-Key, và credential được gửi không phải là key bạn đã tạo.
Kiểm tra ANTHROPIC_AUTH_TOKEN trong cùng output đó, vì nó đứng trước API key theo thứ tự. Một bearer token còn sót lại từ lần thử proxy có nghĩa là key bạn đang sửa hoàn toàn không phải credential được gửi đi. ANTHROPIC_BASE_URL cũng đáng đọc trong output đó, vì một giá trị cũ có thể trỏ client đến một gateway có thể không còn tồn tại. Để hiểu tổng thể ở cấp header, cách xác thực API key của Anthropic hoạt động giải thích mỗi giá trị trong số đó mang gì. Trước khi quyết định máy này thực sự nên giữ credential nào, hãy đọc sự đánh đổi giữa đăng nhập bằng subscription và API key để có thêm bối cảnh.
Một điều mà lỗi này không phải là: vấn đề capacity. Nếu session xác thực thành công rồi request mới fail trong lúc đang hoạt động, bạn đang gặp lỗi model quá tải, và lỗi đó không cần thay đổi credential.
Vì sao script apiKeyHelper của tôi bị lỗi?
apiKeyHelper là một key cấu hình dùng để chỉ định script mà Claude Code chạy để lấy credential. Tính năng này dùng cho token cần xoay vòng hoặc có thời hạn ngắn, chẳng hạn key được lấy từ vault. Contract này đơn giản: in key hiện tại ra standard output rồi thoát thành công. Tài liệu cho biết nếu script thoát với lỗi, hết thời gian chờ hoặc không in gì, các request sẽ thất bại với Your apiKeyHelper script is failing trong vòng ba lần thử.
Chạy script thủ công và kiểm tra cả hai điều kiện của contract:
out=$(/usr/local/bin/anthropic-key.sh)
echo "exit=$? len=${#out} tail=${out: -6}"Thoát với mã khác 0 là lỗi, ngay cả khi key đã được in đúng. Helper cũng bị lỗi nếu in Fetching credential... ra standard output trước key. Từ v2.1.227, Claude Code từ chối output chứa bất kỳ nội dung nào ngoài key và báo rằng helper returned output that cannot be used as an API key. Ở các phiên bản cũ hơn, dòng đó được gửi tiếp như một phần của credential. Hãy gửi thông báo tiến độ sang standard error. Trong một session, /status hiển thị một dòng apiKeyHelper có nội dung Failing, kèm exit code cuối cùng và error output.
Sau đó kiểm tra script theo đúng cách một service sẽ chạy nó:
env -i HOME="$HOME" PATH=/usr/bin:/bin /usr/local/bin/anthropic-key.sh
echo "exit=$?"env -i khởi chạy script với environment gần như rỗng. Helper gọi aws, vault hoặc gcloud từ một directory được .bashrc thêm vào PATH sẽ chạy khi bạn test thủ công nhưng bị lỗi khi chạy thực tế, vì process Claude Code đang chạy chưa đọc .bashrc của bạn. Hãy bảo đảm script có quyền executable và mọi lệnh mà script gọi đều dùng absolute path, hoặc tự đặt PATH bên trong script.
Hai hành vi khác được tài liệu mô tả cũng quan trọng trên server. Theo mặc định, Claude Code chạy lại helper sau 5 phút; CLAUDE_CODE_API_KEY_HELPER_TTL_MS dùng để đặt interval khác. Vì vậy, nếu setup chạy được lúc khởi động nhưng hỏng sau một giờ, lỗi xảy ra trong lúc refresh chứ không phải lúc launch. Nếu helper mất hơn 10 giây để trả về key, Claude Code hiển thị cảnh báo trong prompt bar cùng thời gian đã trôi qua. Cảnh báo đó có nghĩa là lần gọi đang chậm, không phải đã bị lỗi. Đây là dấu hiệu cảnh báo sớm trước khi timeout chuyển thành error.
Bạn có thực sự muốn đặt API key trên máy này không?
Cách xử lý không phải lúc nào cũng là xóa key. Hãy giữ key nếu máy cần được tính phí riêng:
- Một agent không cần tương tác chạy trên VPS được tính phí cho Console sẽ không dùng hạn mức subscription của một người.
- Các lần chạy không tương tác, khi
claude -pkhông có terminal để phê duyệt và luôn dùng key nếu key tồn tại. - Máy không được liên kết với subscription nào.
- Máy dùng chung hoặc máy của khách hàng, nơi tuyệt đối không nên lưu thông tin đăng nhập subscription cá nhân.
Chi phí thường là yếu tố quyết định. Bạn có thể xem so sánh giá API và subscription để quyết định.
Hãy xóa key nếu máy thuộc quyền quản lý của bạn và subscription là dịch vụ bạn đã trả phí. Sau đó, hãy bảo đảm key không quay lại. Thay vì export key trong ~/.bashrc, nơi mọi interactive shell đều kế thừa biến này, hãy chỉ cấp key cho service cần nó:
[Service]
EnvironmentFile=/etc/claude-agent.envGiữ file đó ở mode 600 và đặt owner là user chạy service. Các phiên interactive của bạn sẽ không nhìn thấy file này. Vì vậy, claude của bạn vẫn dùng subscription, còn service tiếp tục dùng key. Nếu cần thông tin xác thực subscription trên máy không có browser, claude setup-token sẽ in OAuth token để bạn dán vào CLAUDE_CODE_OAUTH_TOKEN. Hãy nắm rõ các giới hạn được tài liệu mô tả trước khi phụ thuộc vào cách này: token chỉ có thể gửi model request, nên không dùng được Remote Control session và connector của claude.ai. Quyết định một lần cho từng máy và ghi quyết định đó vào unit file sẽ ngăn lỗi mà trang này đề cập, vì lỗi bắt đầu từ một key mà không ai nhớ đã thiết lập. Giới hạn những gì credential đó có thể truy cập sau khi được cấu hình là một việc khác, được trình bày trong chạy Claude Code an toàn trên VPS.
Một lưu ý trước khi bạn dùng biện pháp mạnh. /logout xóa credential đã lưu. Tài liệu cũng lưu ý rằng lệnh này xóa cả thông tin đăng nhập MCP (model context protocol) server và secret của plugin đã lưu. Vì vậy, bạn sẽ phải xác thực lại các thành phần đó sau đó.
FAQ
Vì sao Claude Code báo API key không hợp lệ dù tôi đã trả phí subscription?
Vì một ANTHROPIC_API_KEY trong environment sẽ được ưu tiên hơn thông tin đăng nhập subscription sau khi bạn đã phê duyệt nó. Tài liệu của Anthropic cho biết key đã được phê duyệt và đặt trong environment sẽ được dùng thay cho subscription Pro, Max, Team hoặc Enterprise, ngay cả khi bạn đã đăng nhập. Ở chế độ non-interactive với -p, key luôn được dùng nếu có mặt. Chạy /status trong Claude Code để xem session đã chọn credential nào. Nếu xuất hiện dòng API key và bạn chưa từng chủ động đặt key này, hãy chạy unset ANTHROPIC_API_KEY rồi khởi động lại claude để xác nhận nguyên nhân.
Chạy /login có sửa được lỗi API key không hợp lệ không?
Không, nếu variable vẫn đang được đặt. /login ghi credential OAuth của subscription, nhưng credential này nằm cuối thứ tự credential của Claude Code, sau các environment variable và sau apiKeyHelper. Lệnh login vẫn thành công nhưng credential vừa tạo sẽ bị bỏ qua, nên chạy lại không thay đổi gì. Hãy xóa variable ở nơi đã đặt nó, hoặc tắt toggle "Use custom API key" trong /config. Theo tài liệu, toggle này chỉ xuất hiện khi ANTHROPIC_API_KEY được đặt trong environment.
Làm cách nào để xem Claude Code đang dùng phương thức xác thực nào?
Chạy /status trong session. Tài liệu mô tả một dòng Login method hiển thị account subscription của bạn và một dòng API key xuất hiện khi đang dùng API key. Đối chiếu kết quả đó với env | grep -i anthropic trong cùng shell mà bạn dùng để khởi chạy. Nếu service hoặc container chạy Claude Code, hãy đọc environment của process bằng tr '\0' '\n' < /proc/<pid>/environ, vì process đang chạy giữ environment được cấp lúc khởi động, không phải environment của shell hiện tại.
Script apiKeyHelper của tôi chạy được khi tôi tự chạy. Vì sao Claude Code vẫn lỗi?
Thường là do environment hoặc exit status. Claude Code chạy helper từ process riêng. Process này chưa đọc shell profile của bạn, nên helper phụ thuộc vào một entry PATH từ .bashrc sẽ lỗi khi chạy trong Claude Code nhưng vẫn hoạt động trong terminal. Kiểm tra bằng env -i HOME="$HOME" PATH=/usr/bin:/bin /path/to/helper và xem echo $? sau đó. Tài liệu cho biết helper sẽ lỗi nếu script exit với error, timeout, không in gì, hoặc in nội dung khác với key; lỗi này hiển thị dưới dạng Your apiKeyHelper script is failing. Từ v2.1.227, banner hoặc log line trên standard output sẽ khiến helper lỗi ngay lập tức. Vì vậy, hãy gửi các message tiến trình sang standard error.