Gemini API가 403 PERMISSION_DENIED를 반환하면 같은 요청을 반복하거나 새 API 키부터 만들지 마세요. 먼저 거부된 작업을 하나로 정해야 합니다. Google AI Studio에서 키를 생성하는 단계인지, Gemini Developer API를 호출하는 단계인지, AI Studio 안에서 생성하는 단계인지, 다른 인증 방식을 요구하는 모델이나 클라이언트 경로인지 확인합니다. HTTP status, 정확한 error message, endpoint hostname, 선택한 project, model, timestamp, request ID를 보존하되 전체 키는 저장하거나 전달하지 않습니다.
| 실패한 위치 | 첫 번째 안전한 확인 | 먼저 하지 말아야 할 일 |
|---|---|---|
| AI Studio에서 키를 만들 수 없음 | 대상 project가 import되었는지 확인하고 관리자에게 resourcemanager.projects.get, iam.serviceAccountApiKeyBindings.create를 확인 요청 | 한 작업 때문에 Owner를 주지 않기 |
models.list를 포함한 모든 호출이 403 | 실제로 읽힌 환경 변수, 키가 속한 project, API/application restriction 확인 | 여러 키를 연속으로 교체하지 않기 |
| 모델 목록은 성공하지만 생성이 403 | model path, action, endpoint, tuned model 인증, project/account policy 확인 | 모델이 보인다는 이유로 생성 권한이 있다고 판단하지 않기 |
| AI Studio가 blocked, suspicious, permission denied 표시 | 로그인한 account와 선택 project, 표시 문구와 시간 보존 | 커뮤니티 사례만으로 계정 정지를 단정하지 않기 |
비밀을 출력하지 않고 변수 존재만 확인합니다.
bashprintf 'GOOGLE_API_KEY=%s\n' "${GOOGLE_API_KEY:+set}" printf 'GEMINI_API_KEY=%s\n' "${GEMINI_API_KEY:+set}"
둘 다 설정되어 있으면 Google의 현재 client library 문서 기준으로 GOOGLE_API_KEY가 우선합니다. Endpoint와 project를 확인한 다음 같은 credential로 모델 목록과 최소 생성 순서의 canary 두 개를 실행합니다. 목록부터 실패하면 키, project, 키 상태, restriction, endpoint를 조사합니다. 목록은 성공하고 생성만 실패하면 model/action/authentication으로 이동합니다. 두 요청이 모두 성공했을 때 local과 deployment configuration을 비교합니다.
정상 설정의 canary가 계속 실패하거나 AI Studio가 여러 정상 키/project에서도 account-level blocked 또는 suspicious를 표시하면 새 객체 생성을 멈춥니다. Sanitized error, project ID, 짧은 키 fingerprint, endpoint, model, timestamp, request ID, canary 결과를 project 관리자나 Google support에 전달합니다.
403은 원인 목록보다 거부된 작업의 관리자를 먼저 찾아야 한다
API 키는 Google Cloud project에 연결된 credential입니다. IAM policy, billing account, quota bucket, model permission, endpoint, AI Studio 로그인 account 자체는 아닙니다. 따라서 키 형식이 맞거나 과거에 성공했다는 사실만으로 현재 action의 권한을 증명할 수 없습니다.
현재 Gemini API 문제 해결 가이드는 403 PERMISSION_DENIED를 필요한 권한이 없는 키의 오류로 설명합니다. 잘못된 키와 올바른 authentication 없이 tuned model을 사용하는 사례도 듭니다. 같은 가이드는 400과 403 같은 client error를 retry하지 말라고 안내합니다. 기다림은 credential, restriction, resource authorization을 바꾸지 않습니다.
한국어 Google의 AI 개요는 지원되지 않는 국가의 무료 등급, 잘못된 키 또는 보안 차단, project/IAM 부족, 서비스 약관과 필터링을 한 화면에 나열합니다. 자연 결과도 공식 문제 해결, “5분 해결” 글, 키 발급 경험, AI Studio 키 생성, caching, GitHub bug를 섞습니다. 이 항목들은 가능한 시나리오일 뿐 같은 처방이 아닙니다. 특히 지역, billing, account enforcement, 콘텐츠 정책을 증거 없이 기본 원인으로 단정하면 안 됩니다.

| 거부된 작업 | 주요 관리자 | 범위를 좁히는 증거 | 가장 작은 다음 행동 |
|---|---|---|---|
| AI Studio 키 생성 | Project import, IAM, organization policy, service-account binding | UI 원문, project ID, account, missing permission | 관리자에게 최소 권한을 요청하거나 자신이 합법적으로 소유한 project 사용 |
| 모델 목록 조회 | Active key, owning project, API/application restriction, endpoint | 변수 이름, fingerprint, hostname, status, sanitized body | 불일치 하나만 수정하고 list canary 반복 |
| 콘텐츠 생성 | Model/action authorization, tuned-model auth, project/account policy | List 결과, model path, generation status, request ID | 같은 경로의 current base model과 비교 |
| AI Studio 내부 생성 | Signed-in account, 선택 project, AI Studio enforcement | UI message, project 선택, timestamp | 소유 관계가 분명해질 때까지 project/key 변경 중단 |
| Local 성공, deployment 실패 | Deployed secret, env precedence, IP/origin restriction, stale revision | 환경별 fingerprint, revision, egress IP/origin | 실제로 어긋난 secret 또는 restriction 하나만 수정 |
설정을 바꾸기 전에 비밀 없는 오류 기록을 만든다
첫 failed request가 가장 깨끗한 증거인 경우가 많습니다. 키 rotation, restriction 수정, project 변경, redeploy 전에 다음을 기록합니다.
- UTC timestamp와 local timezone
- HTTP status, status name, sanitized response body
- endpoint hostname, API version, method
- model 또는 resource path
- 선택하거나 설정한 project ID
- SDK/client version
- response의 request ID, trace ID, correlation ID
- AI Studio, local, CI, production 중 실패 위치
models.list와 최소generateContent의 결과 차이
전체 API 키, 키가 보이는 screenshot, 전체 environment dump, cookie, OAuth token, service-account JSON, 관련 없는 secret, 개인정보가 든 production prompt는 기록하지 않습니다.
Local, CI, production이 같은 credential을 쓰는지 비교할 때는 단방향 짧은 fingerprint를 만들 수 있습니다.
bashif [ -n "${GOOGLE_API_KEY:-}" ]; then ACTIVE_KEY="$GOOGLE_API_KEY" KEY_SOURCE="GOOGLE_API_KEY" elif [ -n "${GEMINI_API_KEY:-}" ]; then ACTIVE_KEY="$GEMINI_API_KEY" KEY_SOURCE="GEMINI_API_KEY" else echo "Gemini API key variable is not set" exit 1 fi printf 'source=%s length=%s sha256=' "$KEY_SOURCE" "${#ACTIVE_KEY}" printf '%s' "$ACTIVE_KEY" | shasum -a 256 | cut -c1-12
12자리 hash prefix는 키가 아닙니다. 두 환경의 secret이 같은지 다른지 판단하는 내부 evidence입니다. Fingerprint도 public issue가 아니라 내부 incident나 안전한 support channel에서만 다루는 편이 좋습니다.
두 단계 canary로 기본 접근과 모델 작업 권한을 분리한다
Canary를 실행할 때 credential, project, endpoint를 고정합니다. Evidence가 가리킨 설정 하나만 변경하고 같은 두 요청을 다시 실행해야 결과가 의미를 가집니다.

Canary 1: 모델 목록
Gemini Developer API는 generativelanguage.googleapis.com을 사용합니다. 다음 명령은 키를 typed command line에 직접 남기지 않고 header descriptor로 전달하며 response body를 local temporary file에 저장합니다.
bashLIST_HTTP=$( curl --silent --show-error \ --output /tmp/gemini-models.json \ --write-out '%{http_code}' \ --header @<(printf 'x-goog-api-key: %s\n' "$ACTIVE_KEY") \ 'https://generativelanguage.googleapis.com/v1beta/models' ) printf 'models.list HTTP %s\n' "$LIST_HTTP" jq '{error, model_count: (.models | length?)}' /tmp/gemini-models.json
- 모델 목록부터 403: active key, project, 키 상태, restriction, endpoint 분기에 남습니다.
- 200과 모델 목록: baseline access는 성공했지만 모든 model/action 권한을 의미하지 않습니다.
- 404 또는 이상한 body: hostname, API version, proxy/base URL, request construction을 먼저 확인합니다.
- 429: permission이 아니라 quota/rate-limit 분기로 이동합니다.
Canary 2: 최소 생성
List response에서 현재 generateContent를 지원하는 model path를 선택합니다. 오래된 글의 model ID를 그대로 복사하지 마세요. Canary도 실제 call이므로 current pricing과 eligibility를 확인합니다.
bashMODEL_PATH='models/<list에서 확인한-generateContent-지원-model>' GEN_HTTP=$( curl --silent --show-error \ --output /tmp/gemini-generate.json \ --write-out '%{http_code}' \ --request POST \ --header @<(printf 'x-goog-api-key: %s\n' "$ACTIVE_KEY") \ --header 'Content-Type: application/json' \ --data '{"contents":[{"parts":[{"text":"OK라고만 답하세요."}]}]}' \ "https://generativelanguage.googleapis.com/v1beta/${MODEL_PATH}:generateContent" ) printf 'generateContent HTTP %s\n' "$GEN_HTTP" jq '{error, candidates: (.candidates | length?)}' /tmp/gemini-generate.json
| 모델 목록 | 생성 | 해석 |
|---|---|---|
| 403 | 실행하지 않음 | Model action 전에 거부: key, project, key state, restriction, endpoint |
| 200 | 403 | Baseline 성공: model/action auth, tuned resource, project/account policy |
| 200 | 404 | Model path, API version, 해당 route의 availability 불일치 |
| 200 | 429 | Permission 성공: quota, tier, traffic shape가 다음 관리자 |
| 200 | 200 | 기본 route 정상: app code, deployed secret, headers, proxy, region 비교 |
Sanitized result를 기록한 뒤 temporary file과 shell variable을 지웁니다.
bashrm -f /tmp/gemini-models.json /tmp/gemini-generate.json unset ACTIVE_KEY
AI Studio에서 “이 project에 키를 만들 권한이 없다”고 할 때
이 오류는 application이 쓸 수 있는 키를 얻기 전에 발생합니다. generateContent, model name, retry logic을 바꿔도 해결되지 않습니다.
현재 Gemini API 키 가이드는 모든 키가 Google Cloud project에 속한다고 설명합니다. AI Studio는 모든 existing project를 자동으로 표시하지 않으므로 Projects view에서 대상 project를 import한 뒤 생성합니다.
현재 AI Studio authorization-key flow에서 Google이 명시한 permission은 다음과 같습니다.
resourcemanager.projects.get: AI Studio가 project를 확인iam.serviceAccountApiKeyBindings.create: service account를 key에 binding
Project 또는 organization admin에게 해당 permission을 포함하는 최소 role을 요청합니다. Google은 Project Editor를 예로 들지만 Editor는 범위가 넓습니다. 관리 조직에서는 승인된 predefined/custom role이 Owner보다 안전합니다.
| 키 작업 | 자주 언급되는 permission/role | 실제 범위 |
|---|---|---|
| Standard Cloud API key 생성 | API Keys Admin(roles/serviceusage.apiKeysAdmin)의 apikeys.keys.create | API Keys service 표준 작업 |
| Current AI Studio authorization key 생성 | resourcemanager.projects.get + iam.serviceAccountApiKeyBindings.create | Project 확인과 service-account binding |
| Tuned/protected resource 사용 | Route/resource별 authentication | 키 생성이 아니라 resource call |
Google Cloud IAM permission reference는 apikeys.keys.create가 API Keys Admin에 포함됨을 확인해 줍니다. 하지만 current authorization-key binding step을 대체하지는 않습니다. 거부된 operation에 permission을 맞춰야 합니다.
관리 권한이 없다면 자신이 합법적으로 소유할 수 있는 organization 밖 project를 고려할 수 있습니다. Organization policy, review, quota, billing, account enforcement를 우회하는 용도로 만들면 안 됩니다.
예전에 작동하던 키가 갑자기 403이 된 경우
애플리케이션이 실제로 다른 키를 읽는지 확인
Client libraries는 GEMINI_API_KEY와 GOOGLE_API_KEY를 자동 인식하며 둘 다 있으면 후자를 우선합니다. 오래된 GOOGLE_API_KEY가 새 값을 가리거나, local과 deployment가 다른 secret manager를 사용하거나, CI variable이 project secret을 override하거나, rotation 후 process가 restart되지 않거나, framework가 별도 provider config를 읽을 수 있습니다. Fingerprint로 증명한 뒤 obsolete duplicate만 제거합니다.
Unrestricted standard key 계약이 바뀐 경우
현재 Google 가이드는 2026년 6월 19일부터 Gemini API가 unrestricted standard key의 request를 거부하기 시작했다고 설명합니다. 명시적 restriction이 있는 standard key는 계속 쓸 수 있고, AI Studio에서 새로 만든 키는 authorization key입니다.
아무 restriction이나 추가하지 마세요. Allowed API, 실제 server IP/web origin, multi-API key 분리 필요성, 새 authorization key로 이동하는 편이 더 안전한지 확인합니다.
Dormant unrestricted key가 Blocked가 된 경우
같은 가이드는 2026년 5월 7일부터 장기간 사용하지 않은 unrestricted key가 차단되어 AI Studio에서 Blocked tag를 표시할 수 있다고 설명합니다. 공개 문서에는 모든 account에 적용되는 하나의 inactivity 기간이 없습니다. 임의의 일수를 만들지 마세요.
새 authorization key 또는 기존 restricted key를 low-risk environment에서 검증하고 replacement가 성공한 뒤 old credential을 비활성화합니다.
Leaked key로 판단된 경우
Google은 알려진 leaked key를 proactive하게 block할 수 있습니다. Replacement를 만들고 local/deployed secret을 업데이트한 뒤 같은 canary를 실행합니다. Usage/billing에서 무단 call을 확인하고 replacement가 통과한 후 old key를 끕니다. Git history, client bundle, logs, screenshots, docs에서 노출 원인을 제거합니다. Full key를 forum이나 일반 support form에 붙이지 않습니다.

API restriction과 application restriction을 따로 확인한다
API restriction은 키가 호출할 수 있는 Google API를 제한합니다. Gemini Developer API에서는 current console의 Generative Language API/Gemini route와 allowed API가 일치해야 합니다. 서로 관계없는 여러 API를 하나의 production key에 묶으면 장애 ownership이 흐려집니다.
Application restriction은 server IP, HTTP referrer, Android app, iOS app으로 사용 출처를 제한합니다. Local은 성공하고 production만 실패하면 egress IP 변경을 확인합니다. Server-only key를 browser에서 호출하면 반대 상황도 생깁니다. 예상 origin이 아니라 실제 request origin을 기록합니다.
Production browser/mobile code에 Gemini key를 넣는 것은 단순 403이 아니라 별도 security incident입니다. Backend proxy로 옮겨도 이미 노출된 키는 살아 있습니다. Replacement, service update, verification, old key disable, exposure source 제거가 모두 필요합니다.
Gemini Developer API와 Vertex AI의 인증을 혼합하지 않는다
위 canary는 generativelanguage.googleapis.com의 Gemini Developer API를 위한 것입니다. Vertex AI는 Google Cloud project/location resource, 다른 endpoint, 다른 identity contract를 사용합니다. Framework가 base URL, provider flag, environment variable로 route를 바꿀 수도 있습니다.
Error에 aiplatform.googleapis.com, location, Vertex publisher model, OAuth, Application Default Credentials, service account가 나오면 Developer API key 절차를 중단합니다. 먼저 Vertex identity/IAM을 확인합니다. 반대로 direct Developer API request에 Gemini라는 이름만 보고 Vertex role을 추가해서도 안 됩니다.
Tuned model만 실패하면 일반 키 교체를 멈춘다
Google의 403 example은 올바른 authentication 없이 tuned model을 사용하는 경우를 별도로 언급합니다. Model owner, calling identity의 authorization, resource path, project, required auth method를 확인하고 같은 route의 base-model canary와 비교합니다.
Base model은 성공하고 tuned model만 실패한다면 새 일반 API 키가 최소 수정일 가능성은 낮습니다. Protected resource의 ACL 또는 authentication을 resource owner가 수정해야 합니다.
400, 404, 429, 5xx는 403과 다른 복구를 사용한다
| HTTP | Google status | 일반적인 관리자 | 첫 행동 |
|---|---|---|---|
| 400 | INVALID_ARGUMENT | Body field, API version, request shape | Current reference와 비교 |
| 400 | FAILED_PRECONDITION | Free tier 미지원 region에서 billing 없음 등 | Region eligibility와 project billing route 확인 |
| 403 | PERMISSION_DENIED | Wrong key, permission, protected action auth | 이 문서의 owner/canary 절차 |
| 404 | NOT_FOUND | Model, file, resource, version | Current model list와 full path 확인 |
| 429 | RESOURCE_EXHAUSTED | RPM, TPM, RPD, spend/project limit | Active project/model limit 확인 |
| 500 | INTERNAL | Service-side failure 또는 request issue | Status 확인, request 축소, 제한적 retry |
| 503 | UNAVAILABLE | Temporary capacity/outage | Status와 jitter 포함 exponential backoff |
| 504 | DEADLINE_EXCEEDED | Deadline 전에 작업 미완료 | Work 축소 또는 적절한 timeout 조정 |
실제 status가 429라면 키를 더 만들지 말고 Gemini API 무료 티어와 실시간 quota 가이드로 이동합니다. Permission 복구 후 usage tier가 문제라면 Gemini API Tier 3 가이드를 확인합니다. Credential과 quota entitlement는 다른 계약입니다.
배포 환경에서 같은 canary가 통과해야 복구가 끝난다
새 키를 만들었다는 사실만으로 복구가 끝나지 않습니다.
- Intended project, endpoint, API version, model path, credential owner 기록
- Replacement 또는 수정된 restriction으로
models.list실행 - 같은 최소 생성 실행
- 실제 deployment에서 반복
- Monitoring, request ID, usage가 예상 project에 속하는지 확인
- Secret manager 업데이트 후 consuming process restart/redeploy
- 올바른 키를 가리는 duplicate variable 제거
- Replacement 성공 후 old key disable
- Temporary response 삭제와 shell variable unset
- Root cause와 실제로 해결한 변경 기록
Rollback은 마지막으로 검증된 restriction 또는 deployment revision으로 돌아가는 것입니다. Leaked key를 다시 활성화하는 것은 rollback이 아닙니다.
관리자와 Google support를 구분해 요청한다
Project를 import/inspect할 수 없거나, current create-key permission이 없거나, organization policy가 key creation/use를 막거나, restriction이 중앙 관리되거나, project/service account/tuned model이 다른 팀 소유라면 project/organization admin에게 요청합니다.
Current key, correct project, endpoint, valid restrictions에서도 sanitized 403이 지속되거나, AI Studio가 clean keys/projects에서 blocked/suspicious를 표시하거나, 거부가 signed-in account를 따라가거나, response가 관리 불가능한 enforcement를 명시하거나, minimal reproduction과 request ID가 있는데 self-service owner가 남지 않았다면 Google로 에스컬레이션합니다.
지원 패킷에는 project ID, source variable과 short fingerprint, endpoint/version/method/model/time, sanitized body, request ID, 두 canary 결과, environment/client version, last success/first failure와 변경 이력만 넣습니다. 전체 키는 필요하지 않습니다.
재발 방지 체크리스트
- Environment마다 명확한 credential owner를 둡니다.
GOOGLE_API_KEY와GEMINI_API_KEY가 조용히 경쟁하지 않게 합니다.- 적절한 경우 current AI Studio authorization-key route를 사용합니다.
- Intended API와 실제 origin에 최소 restriction을 둡니다.
- Production call은 backend를 거치고 key는 secret manager에 둡니다.
- 관련 없는 API/environment는 credentials를 분리합니다.
- Usage/billing anomaly를 감시합니다.
- Exposure 때 rotation하고, 모든 error에 rotation하지 않습니다.
- Model-list/minimal-generation canary를 runbook에 둡니다.
- Launch 전에 project, endpoint, model, restriction owner를 기록합니다.
자주 묻는 질문
Gemini API 키가 403 권한 거부를 받는 이유는 무엇인가요?
Wrong key, 다른 env variable의 shadow, 다른 project, Blocked/leaked state, API/origin restriction 불일치, 또는 baseline access는 있지만 target model/action 권한이 없는 상황일 수 있습니다. 실패 위치와 두 canary부터 확인합니다.
403은 재시도하면 해결되나요?
아닙니다. Google은 403을 client-side permission/authentication error로 분류하고 400/403을 retry하지 말라고 안내합니다. Evidence가 가리키는 관리자 하나만 수정하고 같은 canary를 반복합니다.
AI Studio에서는 되는데 코드에서는 왜 실패하나요?
Account, project, credential, endpoint, model, restriction이 다를 수 있습니다. AI Studio selected project, key owning project, deployed secret fingerprint를 비교합니다.
모델 목록은 되는데 생성만 거부되는 이유는 무엇인가요?
목록은 baseline visibility만 증명합니다. generateContent support, tuned-model ownership, resource path, endpoint, project policy, 정확한 403 body를 확인합니다.
GOOGLE_API_KEY와 GEMINI_API_KEY 중 무엇이 우선하나요?
현재 Google 문서는 둘 다 설정되면 GOOGLE_API_KEY가 우선한다고 설명합니다. 실제 source를 확인한 뒤 obsolete duplicate를 제거합니다.
Google이 오래된 unrestricted key를 차단했나요?
가이드는 2026년 6월 19일부터 unrestricted standard key request를 거부하고, 2026년 5월 7일부터 long-dormant unrestricted key가 차단될 수 있다고 설명합니다. 자신의 key status와 restrictions를 확인해야 하며 모든 old key를 같은 상태로 보면 안 됩니다.
AI Studio 키 생성에 API Keys Admin이 필요한가요?
그 역할만으로 완전한 답은 아닙니다. API Keys Admin은 apikeys.keys.create 같은 standard operation을 포함하지만 current authorization-key flow는 resourcemanager.projects.get과 iam.serviceAccountApiKeyBindings.create를 별도로 명시합니다.
Billing을 활성화하면 403이 해결되나요?
항상 그렇지 않습니다. Google current error table에서 free tier가 지원되지 않는 region에 billing이 없는 한 사례는 400 FAILED_PRECONDITION이고, 403은 permission/authentication입니다. 정확한 status/message를 먼저 읽습니다.
새 project를 만들면 해결되나요?
자신이 합법적으로 소유하는 project는 ownership boundary를 해결할 수 있지만 organization policy, quota, review, account enforcement를 우회하면 안 됩니다. Clean project에서도 account-level denial이 계속되면 생성을 멈추고 evidence로 에스컬레이션합니다.
최종 복구 원칙
Gemini permission denied는 시간 문제가 아니라 ownership 문제로 다룹니다. Denied action, active key, project, endpoint, key state, restrictions, model auth를 증명하고 한 번에 하나만 변경합니다. 같은 canary를 반복하고 deployment에서 확인한 뒤 필요한 경우에만 sanitized evidence로 에스컬레이션합니다.
