# Registry: Error Codes # SSOT: wiki/projects/ca-tmpl/registries/error-codes.yaml # Schema owner: feature-contract-registry-governance # Category enum owner: feature-operational-error-observability-foundation # Last updated: 2026-05-22 # Note: 이 파일은 Phase B 산출물. Phase C2(ca-tmpl 실 코드)에서 generated Java constants의 source. # # Schema (per row): # code: UPPER_SNAKE_CASE # category: VALIDATION | AUTH | AUTHZ | NOT_FOUND | CONFLICT | # RATE_LIMIT | TRANSIENT_DEPENDENCY | PERMANENT_DEPENDENCY | # DATA_INTEGRITY | INTERNAL # http_status: int (async-only failures use 500 placeholder) # retryable: bool # retry_after_seconds: int | null (RATE_LIMIT/TRANSIENT 권고 backoff) # owner_branch: source branch (raw/branch-notes/feature-*.md) # owner_layer: presentation | application | domain | infrastructure | crosscut # client_safe_message: no token / no principal raw / no internal path / no stack trace # log_level: ERROR | WARN | INFO # runbook_link: runbook://area/scenario OR null (client-error만 null 허용) # compatibility_impact: none | additive | behavior-change | breaking # required_test: owning contract test identifier # # Runbook policy (operational-runbook-contract L80): # retryable=false + category ∈ {AUTH, AUTHZ, RATE_LIMIT, INTERNAL, # TRANSIENT_DEPENDENCY, PERMANENT_DEPENDENCY} ⇒ runbook_link 필수. # VALIDATION/NOT_FOUND/CONFLICT/DATA_INTEGRITY는 client-error로 runbook 면제 가능. # retryable=true 인 모든 row는 runbook_link 필수. errors: # ============================================================ # AUTH (feature-security-operational-baseline / Decision Matrix) # ============================================================ # source: feature-security-operational-baseline L82 — "token 누락 | 401 | AUTH_TOKEN_MISSING | AUTH" - code: AUTH_TOKEN_MISSING category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication required" log_level: WARN runbook_link: "runbook://auth/token-missing" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L83 — "token malformed (parse fail) | 401 | AUTH_TOKEN_MALFORMED | AUTH" - code: AUTH_TOKEN_MALFORMED category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed" log_level: WARN runbook_link: "runbook://auth/token-malformed" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L84 — "token expired (clock skew tolerance 60s 초과) | 401 | AUTH_TOKEN_EXPIRED | AUTH" - code: AUTH_TOKEN_EXPIRED category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication expired" log_level: WARN runbook_link: "runbook://auth/token-expired" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L85 — "invalid signature | 401 | AUTH_TOKEN_INVALID_SIGNATURE | AUTH" - code: AUTH_TOKEN_INVALID_SIGNATURE category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed" log_level: ERROR runbook_link: "runbook://auth/token-invalid-signature" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L86 — "issuer mismatch | 401 | AUTH_ISSUER_MISMATCH | AUTH" - code: AUTH_ISSUER_MISMATCH category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed" log_level: ERROR runbook_link: "runbook://auth/issuer-mismatch" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L87 — "audience mismatch | 401 | AUTH_AUDIENCE_MISMATCH | AUTH" - code: AUTH_AUDIENCE_MISMATCH category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed" log_level: ERROR runbook_link: "runbook://auth/audience-mismatch" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L88 — "unknown kid (JWKS 미캐시) | 401 + Retry-After 5s | AUTH_KID_UNKNOWN | AUTH" - code: AUTH_KID_UNKNOWN category: AUTH http_status: 401 retryable: true # 2026-06-01: false→true. JWKS 키 회전 중 unknown kid 는 ~5s 후 JWKS refresh 로 해소 가능(transient). retry_after_seconds=5 + client_safe_message "please retry" 와 정합. 키 고정 정책으로 전환 시 false 복귀. retry_after_seconds: 5 owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed, please retry" log_level: WARN runbook_link: "runbook://auth/kid-unknown" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L89 — "JWKS endpoint outage ... | AUTH_JWKS_UNAVAILABLE | TRANSIENT_DEPENDENCY" - code: AUTH_JWKS_UNAVAILABLE category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 30 owner_branch: feature-security-operational-baseline owner_layer: infrastructure client_safe_message: "Authentication service temporarily unavailable" log_level: ERROR runbook_link: "runbook://auth/jwks-unavailable" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-security-operational-baseline L90 — "claim mapping failure ... | 401 | AUTH_CLAIM_MAPPING_FAILED | AUTH" - code: AUTH_CLAIM_MAPPING_FAILED category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Authentication failed" log_level: ERROR runbook_link: "runbook://auth/claim-mapping-failed" compatibility_impact: none required_test: contract-verification:auth-category # ============================================================ # AUTHZ (feature-security-operational-baseline) # ============================================================ # source: feature-security-operational-baseline L91 — "valid token + 권한 부족 | 403 | AUTHZ_INSUFFICIENT_PERMISSION | AUTHZ" - code: AUTHZ_INSUFFICIENT_PERMISSION category: AUTHZ http_status: 403 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Permission denied" log_level: WARN runbook_link: "runbook://authz/insufficient-permission" compatibility_impact: none required_test: contract-verification:authz-category # source: feature-security-operational-baseline L92 — "valid token + tenant cross-access | 403 | AUTHZ_TENANT_MISMATCH | AUTHZ" - code: AUTHZ_TENANT_MISMATCH category: AUTHZ http_status: 403 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: presentation client_safe_message: "Permission denied" log_level: ERROR runbook_link: "runbook://authz/tenant-mismatch" compatibility_impact: none required_test: contract-verification:authz-category # ============================================================ # INTERNAL (feature-security-operational-baseline + container-runtime) # ============================================================ # source: feature-security-operational-baseline L93 — "public path misconfiguration ... | 500 + P1 alert | INTERNAL_AUTH_MISCONFIGURATION | INTERNAL" - code: INTERNAL_AUTH_MISCONFIGURATION category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-security-operational-baseline owner_layer: crosscut client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://auth/public-path-misconfiguration" compatibility_impact: none required_test: contract-verification:auth-category # source: feature-container-runtime-contract L113 — "JVM OutOfMemoryError → ExitOnOutOfMemoryError로 137 exit, log에 error.code=JVM_OOM 명시" - code: JVM_OOM category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-container-runtime-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://runtime/jvm-oom" compatibility_impact: none required_test: contract-verification:container-runtime-oom # ============================================================ # DB / Persistence (feature-persistence-failure-baseline / SQLState Matrix) # ============================================================ # source: feature-persistence-failure-baseline L85 — "08* | all | TRANSIENT_DEPENDENCY | DB_UNAVAILABLE | true" - code: DB_UNAVAILABLE category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 5 owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Service temporarily unavailable" log_level: ERROR runbook_link: "runbook://db/unavailable" compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L86 — "40001 | Postgres/MySQL | CONFLICT | DB_SERIALIZATION_FAILURE | true" - code: DB_SERIALIZATION_FAILURE category: CONFLICT http_status: 409 retryable: true retry_after_seconds: 1 owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request conflicted with another transaction, please retry" log_level: WARN runbook_link: "runbook://db/serialization-failure" compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L87 — "40P01 | Postgres | CONFLICT | DB_DEADLOCK | true (backoff)" - code: DB_DEADLOCK category: CONFLICT http_status: 409 retryable: true retry_after_seconds: 1 owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request conflicted, please retry" log_level: WARN runbook_link: "runbook://db/deadlock" compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L88 — "23502 | Postgres | DATA_INTEGRITY | DB_NULL_VIOLATION | false" - code: DB_NULL_VIOLATION category: DATA_INTEGRITY http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request violates a required field constraint" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L89 — "23503 | Postgres | DATA_INTEGRITY | DB_FK_VIOLATION | false" - code: DB_FK_VIOLATION category: DATA_INTEGRITY http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request references missing resource" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L90 — "23505 | Postgres | CONFLICT | DB_UNIQUE_VIOLATION | false (business mapping)" - code: DB_UNIQUE_VIOLATION category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Resource already exists" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L91 — "23514 | Postgres | DATA_INTEGRITY | DB_CHECK_VIOLATION | false" - code: DB_CHECK_VIOLATION category: DATA_INTEGRITY http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request violates a value constraint" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L92 — "25P03 | Postgres | TRANSIENT_DEPENDENCY | DB_IDLE_IN_TX_TIMEOUT | true" - code: DB_IDLE_IN_TX_TIMEOUT category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 2 owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Service temporarily unavailable" log_level: ERROR runbook_link: "runbook://db/idle-in-tx-timeout" compatibility_impact: none required_test: contract-verification:persistence-mapping # source: feature-persistence-failure-baseline L93 — "57014 | Postgres | TRANSIENT_DEPENDENCY | DB_QUERY_CANCELED | false" - code: DB_QUERY_CANCELED category: TRANSIENT_DEPENDENCY http_status: 503 retryable: false retry_after_seconds: null owner_branch: feature-persistence-failure-baseline owner_layer: infrastructure client_safe_message: "Request was canceled, please retry later" log_level: WARN runbook_link: "runbook://db/query-canceled" compatibility_impact: none required_test: contract-verification:persistence-mapping # ============================================================ # Rate limit / Idempotency (feature-rate-limit-idempotency-contract) # ============================================================ # source: feature-rate-limit-idempotency-contract — rate limit response/log 기준 / Retry-After header 기준 (scope L29, L33) - code: RATE_LIMIT_EXCEEDED category: RATE_LIMIT http_status: 429 retryable: true retry_after_seconds: 1 owner_branch: feature-rate-limit-idempotency-contract owner_layer: presentation client_safe_message: "Too many requests, please retry after the indicated interval" log_level: WARN runbook_link: "runbook://rate-limit/exceeded" compatibility_impact: none required_test: contract-verification:rate-limit # source: feature-rate-limit-idempotency-contract L71 — "200ms 초과 시 409 IDEMPOTENT_IN_FLIGHT (retryable=false, client는 polling)" - code: IDEMPOTENT_IN_FLIGHT category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-rate-limit-idempotency-contract owner_layer: application client_safe_message: "A previous identical request is still being processed, please poll for result" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:idempotency # source: feature-rate-limit-idempotency-contract L72 — "fingerprint mismatch (same key + different body) = 422 IDEMPOTENT_REQUEST_MISMATCH" - code: IDEMPOTENT_REQUEST_MISMATCH category: VALIDATION http_status: 422 retryable: false retry_after_seconds: null owner_branch: feature-rate-limit-idempotency-contract owner_layer: application client_safe_message: "Idempotency key reused with different request body" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:idempotency # ============================================================ # File / Resource (feature-file-resource-handling-contract) # ============================================================ # source: feature-file-resource-handling-contract L69 — "spring.servlet.multipart.max-file-size 10MB ... Spring 단의 enforcement가 실패 시 envelope 응답 보장" / 테스트 계약 "oversized upload가 generic 500으로 처리되면 실패" - code: UPLOAD_SIZE_EXCEEDED category: VALIDATION http_status: 413 retryable: false retry_after_seconds: null owner_branch: feature-file-resource-handling-contract owner_layer: presentation client_safe_message: "Uploaded file exceeds maximum size" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:file-upload # source: feature-file-resource-handling-contract L72 — "allowed content-type allowlist starting set ..." - code: UPLOAD_CONTENT_TYPE_REJECTED category: VALIDATION http_status: 415 retryable: false retry_after_seconds: null owner_branch: feature-file-resource-handling-contract owner_layer: presentation client_safe_message: "Uploaded content type is not allowed" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:file-upload # source: feature-file-resource-handling-contract — Decisionized Work Items "path traversal | normalized storage key only ... | traversal test" - code: PATH_TRAVERSAL_DETECTED category: VALIDATION http_status: 400 retryable: false retry_after_seconds: null owner_branch: feature-file-resource-handling-contract owner_layer: presentation client_safe_message: "Invalid file path" log_level: ERROR runbook_link: null compatibility_impact: none required_test: contract-verification:file-upload # source: feature-file-resource-handling-contract L73 — "streaming download backpressure = response timeout 60s, max stream 100MB. 초과 시 truncate + ERROR log" - code: DOWNLOAD_STREAMING_FAILURE category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 5 owner_branch: feature-file-resource-handling-contract owner_layer: presentation client_safe_message: "Download failed, please retry" log_level: ERROR runbook_link: "runbook://file/download-streaming-failure" compatibility_impact: none required_test: contract-verification:file-download # ============================================================ # API contract transport-standard codes (feature-api-contract-baseline) # ============================================================ # NOTE: feature-api-contract-baseline owns the transport-shape failure # classification (D8 413/414, D9 406/415, D12 405, D15 412). These rows mirror # dev.caskeleton.shared.error.OperationalError; the D11 status-mapping # consistency test (owner: this branch, producer) fails the build when a code's # registry http_status and the enum httpStatus() drift apart. # source: feature-api-contract-baseline.md D12 — "405 Method Not Allowed + Allow header 의무" - code: METHOD_NOT_ALLOWED category: VALIDATION http_status: 405 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "HTTP method not allowed for this resource" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # source: feature-api-contract-baseline.md D9 — "406 Not Acceptable = 응답 표현 협상 실패" - code: NOT_ACCEPTABLE category: VALIDATION http_status: 406 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "No acceptable representation for the requested Accept header" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # source: feature-api-contract-baseline.md D15 — "If-Match mismatch 시 412 Precondition Failed" - code: PRECONDITION_FAILED category: CONFLICT http_status: 412 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "Resource was modified by another request; refetch and retry" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # source: feature-api-contract-baseline.md D8 — "request size limit 실패 분류 (413)" - code: PAYLOAD_TOO_LARGE category: VALIDATION http_status: 413 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "Request payload is too large" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # source: feature-api-contract-baseline.md D8 형제 — "URI 길이 실패 분류 (414)" # NOTE: enforcement is Tomcat/gateway-owned (rejected before Spring dispatch); # this row + code exist for status-mapping consistency. End-to-end 414 contract # test is `planned` (gateway/Tomcat maxHttpHeaderSize 8KB boundary). - code: URI_TOO_LONG category: VALIDATION http_status: 414 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "Request URI is too long" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # source: feature-api-contract-baseline.md D9 — "415 Unsupported Media Type = 요청 본문 format 미지원" - code: UNSUPPORTED_MEDIA_TYPE category: VALIDATION http_status: 415 retryable: false retry_after_seconds: null owner_branch: feature-api-contract-baseline owner_layer: presentation client_safe_message: "Request Content-Type is not supported" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:api-contract-status-mapping # ============================================================ # Tenant (feature-tenant-context-policy) # ============================================================ # source: feature-tenant-context-policy L71 — "tenant 미지원 모드에서 X-Tenant-Id 헤더 수신 시 400 TENANT_NOT_SUPPORTED (filter 단계)" - code: TENANT_NOT_SUPPORTED category: VALIDATION http_status: 400 retryable: false retry_after_seconds: null owner_branch: feature-tenant-context-policy owner_layer: presentation client_safe_message: "Tenant context is not supported by this deployment" log_level: WARN runbook_link: null compatibility_impact: none required_test: contract-verification:tenant-policy # ============================================================ # Validation / Business rule (feature-business-rule-validation-contract) # ============================================================ # NOTE: business-rule-validation branch는 mapping 규칙 SSOT (syntax→VALIDATION, # policy→AUTHZ/CONFLICT, invariant→CONFLICT/VALIDATION, persistence→PERSISTENCE/CONFLICT) # 이며 구체 code는 example로 VALIDATION_EMAIL_FORMAT만 등장 # (feature-operational-error-observability-foundation L110). 실제 도메인별 code는 # Phase D(도메인 feature 적용) 시 본 registry에 추가. # source: feature-operational-error-observability-foundation L110 — "code: VALIDATION_EMAIL_FORMAT, // registry-registered code" (validation field error JSON shape example) - code: VALIDATION_EMAIL_FORMAT category: VALIDATION http_status: 400 retryable: false retry_after_seconds: null owner_branch: feature-operational-error-observability-foundation owner_layer: presentation client_safe_message: "Invalid email format" log_level: INFO runbook_link: null compatibility_impact: none required_test: contract-verification:validation-envelope # ============================================================ # Cache (feature-cache-consistency-contract) # ============================================================ # source: feature-cache-consistency-contract — Decisionized Work Items "Redis unavailable | degrade only if declared | fail-fast for required cache | generic INTERNAL | unavailable mapping" / 테스트 "Redis unavailable이 degrade 가능 여부 없이 INTERNAL로 처리되면 실패" - code: CACHE_UNAVAILABLE category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 2 owner_branch: feature-cache-consistency-contract owner_layer: infrastructure client_safe_message: "Service temporarily unavailable" log_level: ERROR runbook_link: "runbook://cache/unavailable" compatibility_impact: none required_test: contract-verification:cache-consistency # source: feature-cache-consistency-contract L70 — "stampede 방지 default = single-instance Caffeine local lock, multi-instance HPA 시 Redisson RLock distributed mutex" / 테스트 "동일 key에 대해 동시 cache miss 시 backend 호출이 1회로 제한되는지 verify (stampede). 미충족 시 실패" - code: CACHE_STAMPEDE_LOCK_TIMEOUT category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 1 owner_branch: feature-cache-consistency-contract owner_layer: infrastructure client_safe_message: "Service temporarily unavailable" log_level: WARN runbook_link: "runbook://cache/stampede-lock-timeout" compatibility_impact: none required_test: contract-verification:cache-consistency # ============================================================ # Outbound HTTP (feature-outbound-http-client-baseline) # ============================================================ # source: feature-outbound-http-client-baseline L70 — "outbound HTTP timeout default = connect 2s / read 5s / global call 10s" + scope "timeout/connect/DNS failure 분류" / 테스트 "upstream timeout은 retryable dependency failure로 분류되어야 함" - code: DEPENDENCY_TIMEOUT category: TRANSIENT_DEPENDENCY http_status: 504 retryable: true retry_after_seconds: 2 owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service did not respond in time, please retry" log_level: ERROR runbook_link: "runbook://dependency/timeout" compatibility_impact: none required_test: contract-verification:outbound-http # source: feature-outbound-http-client-baseline — scope "timeout/connect/DNS failure 분류" + L70 connect=2s timeout - code: DEPENDENCY_CONNECT_FAILED category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 2 owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service unreachable, please retry" log_level: ERROR runbook_link: "runbook://dependency/connect-failed" compatibility_impact: none required_test: contract-verification:outbound-http # source: feature-outbound-http-client-baseline — scope "timeout/connect/DNS failure 분류" - code: DEPENDENCY_DNS_FAILED category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 5 owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service unreachable, please retry" log_level: ERROR runbook_link: "runbook://dependency/dns-failed" compatibility_impact: none required_test: contract-verification:outbound-http # source: feature-outbound-http-client-baseline — scope "upstream 4xx/5xx 분류" / 테스트 "401/403은 credential/scope/config 문제로 분류되어야 함" - code: DEPENDENCY_4XX_CLIENT category: PERMANENT_DEPENDENCY http_status: 502 retryable: false retry_after_seconds: null owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service rejected the request" log_level: ERROR runbook_link: "runbook://dependency/4xx-client" compatibility_impact: none required_test: contract-verification:outbound-http # source: feature-outbound-http-client-baseline — scope "upstream 4xx/5xx 분류" - code: DEPENDENCY_5XX_SERVER category: TRANSIENT_DEPENDENCY http_status: 502 retryable: true retry_after_seconds: 2 owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service error, please retry" log_level: ERROR runbook_link: "runbook://dependency/5xx-server" compatibility_impact: none required_test: contract-verification:outbound-http # source: feature-outbound-http-client-baseline L69 — "circuit breaker metric은 dependency.name, dependency.type, outcome까지만 tag로 허용" + Decisionized "circuit breaker | Resilience4j optional env" - code: DEPENDENCY_CIRCUIT_OPEN category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 10 owner_branch: feature-outbound-http-client-baseline owner_layer: infrastructure client_safe_message: "Upstream service temporarily unavailable, please retry later" log_level: WARN runbook_link: "runbook://dependency/circuit-open" compatibility_impact: none required_test: contract-verification:outbound-http # ============================================================ # Outbox (feature-domain-event-outbox-contract) # ============================================================ # source: feature-domain-event-outbox-contract L67 — "outbox row status enum = PENDING / IN_FLIGHT / PUBLISHED / FAILED / DEAD" + scope "publish 실패 분류" / 판정 "publish 실패가 retry/DLQ/log/runbook 기준 없이 삼켜지면 실패" - code: OUTBOX_PUBLISH_FAILED category: TRANSIENT_DEPENDENCY http_status: 500 retryable: true retry_after_seconds: 30 owner_branch: feature-domain-event-outbox-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://outbox/publish-failed" compatibility_impact: none required_test: contract-verification:outbox-publish # source: feature-domain-event-outbox-contract L67 — outbox status enum "DEAD" / Outbox Defaults "DLQ | background-job branch owner" - code: OUTBOX_DEAD_LETTER category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-domain-event-outbox-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://outbox/dead-letter" compatibility_impact: none required_test: contract-verification:outbox-dlq # ============================================================ # Background job / Async (feature-background-job-async-contract) # ============================================================ # source: feature-background-job-async-contract — Decisionized "saturation | bounded executor + rejection log" / L72 "saturation policy default = AbortPolicy" / 테스트 "executor rejection이 structured log 없이 발생하면 실패" - code: JOB_EXECUTOR_REJECTED category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 5 owner_branch: feature-background-job-async-contract owner_layer: infrastructure client_safe_message: "Service temporarily unavailable" log_level: ERROR runbook_link: "runbook://job/executor-rejected" compatibility_impact: none required_test: contract-verification:async-saturation # source: feature-background-job-async-contract L69 — "기본 backoff는 exponential backoff with jitter, max attempts 3, DLQ after exhausted attempts" + scope "shutdown 중 job 처리 기준" / L73 graceful shutdown ≤19s - code: JOB_TIMEOUT category: TRANSIENT_DEPENDENCY http_status: 500 retryable: true retry_after_seconds: 10 owner_branch: feature-background-job-async-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://job/timeout" compatibility_impact: none required_test: contract-verification:async-timeout # source: feature-background-job-async-contract L69 — "DLQ after exhausted attempts" + Decisionized "retry/DLQ | exp backoff jitter, max 3, DLQ exhausted | ... | infinite retry" - code: JOB_DEAD_LETTER category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-background-job-async-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://job/dead-letter" compatibility_impact: none required_test: contract-verification:async-dlq # ============================================================ # Distributed Lock (feature-distributed-lock-contract) # ============================================================ # source: feature-distributed-lock-contract D7 — "lock 획득 실패/timeout 의 error code = # LOCK_ACQUISITION_TIMEOUT (category CONFLICT, retryable true, client_safe true) + metric # lock.acquisition" / D5 — "try-lock + 유한 waitTime + lease(TTL) 필수, 무한 blocking 금지". # category CONFLICT 는 기존 enum 재사용; retryable=true — 락 보유자가 임계 구역을 빠져나오면 # 동일 요청 재시도로 해소된다(transient contention). DB_DEADLOCK / DB_SERIALIZATION_FAILURE 와 # 같은 retryable CONFLICT 계열(409). 본 코드는 distributedLockProvider 획득 timeout 전용이며 # cache stampede lock 의 CACHE_STAMPEDE_LOCK_TIMEOUT(cache-consistency, TRANSIENT_DEPENDENCY 503) # 과 의미가 구분된다 — 후자는 캐시 백엔드 의존성 timeout, 전자는 분산 상호배제 contention. - code: LOCK_ACQUISITION_TIMEOUT category: CONFLICT http_status: 409 retryable: true retry_after_seconds: 1 owner_branch: feature-distributed-lock-contract owner_layer: infrastructure client_safe_message: "Resource is busy, please retry" log_level: WARN runbook_link: "runbook://lock/acquisition-timeout" compatibility_impact: none required_test: contract-verification:lock-acquisition-timeout # ============================================================ # Migration / Startup (feature-migration-startup-contract) # ============================================================ # source: feature-migration-startup-contract L71 — "startup exit code 표준 = ... migration 실패=70 ..." + Decisionized "startup failure log | structured log with startup.phase, error.code, error.category" - code: MIGRATION_FAILED category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-migration-startup-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://migration/failed" compatibility_impact: none required_test: contract-verification:migration-startup # source: feature-migration-startup-contract L71 — "startup exit code 표준 = env 누락/malformed=78 ..." / 테스트 "required env 누락 시 startup이 성공하면 실패" - code: STARTUP_VALIDATION_FAILED category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-migration-startup-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://startup/validation-failed" compatibility_impact: none required_test: contract-verification:migration-startup # source: feature-migration-startup-contract L71 — "startup exit code 표준 = ... required adapter disabled=72" / 테스트 "disabled required adapter로 app이 뜨면 실패" - code: REQUIRED_ADAPTER_DISABLED category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-migration-startup-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://startup/required-adapter-disabled" compatibility_impact: none required_test: contract-verification:migration-startup # source: feature-integration-adapter-templates §구현 가이드 §4 (Layer 3) + §Audit A2. # Runtime-lifecycle fail-fast for an invoke against a DISABLED optional adapter # (Kafka/Redis/Slack/Google Email). Deliberately distinct from the startup-lifecycle # REQUIRED_ADAPTER_DISABLED above (exit 72): a runtime invoke ≠ a startup validation, # so reusing the startup code would conflate two lifecycles (A2 resolution — new # runtime code owned by this branch). retryable=false: the adapter stays disabled # until redeploy, so retrying the same call never clears it. - code: ADAPTER_DISABLED category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-integration-adapter-templates owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://adapter/adapter-disabled" compatibility_impact: none required_test: adapter-contract:adapter-disabled-runtime-call # source: feature-migration-startup-contract L71 — "startup exit code 표준 = ... profile mismatch=71" / 테스트 "prod profile에서 local-only 설정이 켜지면 실패" - code: PROFILE_MISMATCH category: INTERNAL http_status: 500 retryable: false retry_after_seconds: null owner_branch: feature-migration-startup-contract owner_layer: infrastructure client_safe_message: "Internal server error" log_level: ERROR runbook_link: "runbook://startup/profile-mismatch" compatibility_impact: none required_test: contract-verification:migration-startup # ============================================================ # Management / Actuator (feature-management-actuator-security-contract) # ============================================================ # source: feature-management-actuator-security-contract — Exposure Policy "env/configprops | forbidden" "heapdump/threaddump | forbidden unless break-glass runbook" "shutdown | forbidden" / 테스트 "prod에서 env/configprops endpoint가 노출되면 실패" - code: ACTUATOR_FORBIDDEN category: AUTHZ http_status: 403 retryable: false retry_after_seconds: null owner_branch: feature-management-actuator-security-contract owner_layer: presentation client_safe_message: "Permission denied" log_level: WARN runbook_link: "runbook://management/actuator-forbidden" compatibility_impact: none required_test: contract-verification:management-actuator # ============================================================ # TECH LOG STUDIO (studio-v1.yaml ApiError.code — 23종, feature-techlog-studio-backend) # # StudioError(dev.caskeleton.application.techlog.error.StudioError)와 1:1 매핑. # category/http_status/retryable은 그 enum의 선언과 정확히 같아야 한다 # (StudioErrorRegistryTest가 코드 존재만 보고, 값 일치는 이 파일의 리뷰 책임). # # PAYLOAD_TOO_LARGE / UNSUPPORTED_MEDIA_TYPE은 StudioError에도 있지만 별도 row를 # 추가하지 않는다 — feature-api-contract-baseline이 이미 동일 code로 아래(L514, # L545)에 VALIDATION/413/415/false, VALIDATION/415/false row를 갖고 있고 값이 # StudioError 선언과 정확히 일치한다. error-codes.yaml의 identity column은 `code` # 하나뿐이라 같은 code로 두 번째 row를 추가하면 ContractRegistrySchemaGovernanceTest # 의 "duplicate identity" 게이트가 깨진다. 즉 이 두 코드는 기존 row가 이미 커버한다. # ============================================================ # source: studio-v1.yaml ApiError.code — AUTHENTICATION_REQUIRED (StudioError.AUTHENTICATION_REQUIRED) - code: AUTHENTICATION_REQUIRED category: AUTH http_status: 401 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: presentation client_safe_message: "Studio 인증이 필요합니다" log_level: INFO runbook_link: "runbook://auth/token-missing" compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — STUDIO_ACCESS_DENIED (StudioError.STUDIO_ACCESS_DENIED) - code: STUDIO_ACCESS_DENIED category: AUTHZ http_status: 403 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "이 Studio 리소스에 접근할 권한이 없습니다" log_level: WARN runbook_link: "runbook://authz/insufficient-permission" compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml + studio-management-v1.yaml ApiError.code — DOCUMENT_NOT_FOUND # (StudioError.DOCUMENT_NOT_FOUND, ManagementError.DOCUMENT_NOT_FOUND) # # 두 표면이 같은 코드를 쓴다. 이 레지스트리의 식별자는 code 하나뿐이므로 행도 하나다 — # 한때 표면마다 행을 두고 문구를 다르게 적었고("작업본을 찾을 수 없습니다"), 그 중복이 # 레지스트리 로딩 자체를 깨뜨렸다. 같은 코드는 같은 말을 해야 한다. - code: DOCUMENT_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 문서를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — VERSION_CONFLICT (StudioError.VERSION_CONFLICT) - code: VERSION_CONFLICT category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "저장된 version이 더 최신입니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — REQUEST_VALIDATION_FAILED (StudioError.REQUEST_VALIDATION_FAILED) - code: REQUEST_VALIDATION_FAILED category: VALIDATION http_status: 422 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: presentation client_safe_message: "요청 형식이 올바르지 않습니다" log_level: WARN runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — DOCUMENT_VALIDATION_FAILED # (StudioError.DOCUMENT_VALIDATION_FAILED). 원래 계약 이름은 VALIDATION_FAILED였으나 # 스켈레톤 전역 OperationalError.VALIDATION_FAILED(400, VALIDATION)와 code 문자열이 # 충돌해(같은 문자열, 다른 http_status) 개명했다 — controller 판정, 2026-08-19. - code: DOCUMENT_VALIDATION_FAILED category: VALIDATION http_status: 422 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "문서 검증에 실패했습니다" log_level: WARN runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — VALIDATION_STALE (StudioError.VALIDATION_STALE) - code: VALIDATION_STALE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "검증 결과가 최신 문서 기준이 아닙니다. 다시 검증해 주세요" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PREVIEW_NOT_FOUND (StudioError.PREVIEW_NOT_FOUND) - code: PREVIEW_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 미리보기를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PREVIEW_STALE (StudioError.PREVIEW_STALE) - code: PREVIEW_STALE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "미리보기가 최신 문서 기준이 아닙니다. 다시 생성해 주세요" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PREVIEW_EXPIRED (StudioError.PREVIEW_EXPIRED) - code: PREVIEW_EXPIRED category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "미리보기가 만료되었습니다. 다시 생성해 주세요" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PUBLICATION_NOT_FOUND (StudioError.PUBLICATION_NOT_FOUND) - code: PUBLICATION_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 게시물을 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PUBLICATION_CONFLICT (StudioError.PUBLICATION_CONFLICT) - code: PUBLICATION_CONFLICT category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "게시 작업이 다른 변경과 충돌했습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PUBLICATION_EVENT_NOT_FOUND (StudioError.PUBLICATION_EVENT_NOT_FOUND) - code: PUBLICATION_EVENT_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 게시 이벤트를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — PUBLICATION_SNAPSHOT_NOT_FOUND (StudioError.PUBLICATION_SNAPSHOT_NOT_FOUND) - code: PUBLICATION_SNAPSHOT_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 게시 스냅샷을 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — WARNING_ACKNOWLEDGEMENT_REQUIRED (StudioError.WARNING_ACKNOWLEDGEMENT_REQUIRED) - code: WARNING_ACKNOWLEDGEMENT_REQUIRED category: VALIDATION http_status: 422 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "경고 확인이 필요합니다. 확인 후 다시 시도해 주세요" log_level: WARN runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — IDEMPOTENCY_KEY_REUSED (StudioError.IDEMPOTENCY_KEY_REUSED) - code: IDEMPOTENCY_KEY_REUSED category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "Idempotency 키가 다른 요청에 재사용되었습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — ASSET_NOT_FOUND (StudioError.ASSET_NOT_FOUND) - code: ASSET_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "요청한 자산을 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — ASSET_NOT_READY (StudioError.ASSET_NOT_READY) - code: ASSET_NOT_READY category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "자산 처리가 아직 완료되지 않았습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — ASSET_IN_USE (StudioError.ASSET_IN_USE) - code: ASSET_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "자산이 사용 중이라 이 작업을 수행할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — ASSET_QUARANTINED (StudioError.ASSET_QUARANTINED) - code: ASSET_QUARANTINED category: DATA_INTEGRITY http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-studio-backend owner_layer: application client_safe_message: "자산이 격리 처리되어 사용할 수 없습니다" log_level: WARN runbook_link: null compatibility_impact: additive required_test: StudioErrorTest # source: studio-v1.yaml ApiError.code — STUDIO_UNAVAILABLE (StudioError.STUDIO_UNAVAILABLE) - code: STUDIO_UNAVAILABLE category: TRANSIENT_DEPENDENCY http_status: 503 retryable: true retry_after_seconds: 5 owner_branch: feature-techlog-studio-backend owner_layer: infrastructure client_safe_message: "Studio 서비스를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요" log_level: ERROR runbook_link: "runbook://studio/unavailable" compatibility_impact: additive required_test: StudioErrorTest # === Tech Log Public (feature-techlog-public-v1) === # # public-v1.yaml 의 ApiError.code 는 세 값이다. 나머지 하나 INTERNAL_ERROR 는 스켈레톤 # 공통 코드로 이미 이 레지스트리에 있으므로 여기서 다시 선언하지 않는다. # # Studio 와 이름을 겹치지 않게 한 이유: 이 레지스트리는 코드 하나에 http_status 하나만 # 담는다. public 의 400 과 studio 의 422 를 같은 이름으로 쓸 수 없다. # source: public-v1.yaml ApiError.code — PUBLIC_REQUEST_INVALID (PublicError.PUBLIC_REQUEST_INVALID) - code: PUBLIC_REQUEST_INVALID category: VALIDATION http_status: 400 retryable: false retry_after_seconds: null owner_branch: feature-techlog-public-v1 owner_layer: application client_safe_message: "요청 값이 올바르지 않습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: PublicErrorRegistryTest # source: public-v1.yaml ApiError.code — PUBLIC_RESOURCE_NOT_FOUND (PublicError.PUBLIC_RESOURCE_NOT_FOUND) - code: PUBLIC_RESOURCE_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-public-v1 owner_layer: application client_safe_message: "요청한 자료를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: PublicErrorRegistryTest # --------------------------------------------------------------------------- # TECH LOG STUDIO MANAGEMENT (studio-management-v1.yaml ApiError.code) # # ManagementError(dev.caskeleton.application.techlog.error.ManagementError)와 1:1. # AUTHENTICATION_REQUIRED / STUDIO_ACCESS_DENIED / REQUEST_VALIDATION_FAILED / # VERSION_CONFLICT 는 StudioError 에도 있어 행이 이미 존재한다 — 이 파일의 identity # column 은 `code` 이므로 중복 행을 만들지 않는다. # --------------------------------------------------------------------------- # source: studio-management-v1.yaml ApiError.code — TOPIC_NOT_FOUND (ManagementError.TOPIC_NOT_FOUND) - code: TOPIC_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "주제를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — TOPIC_NAME_TAKEN (ManagementError.TOPIC_NAME_TAKEN) - code: TOPIC_NAME_TAKEN category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "같은 이름의 주제가 이미 있습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — TOPIC_SLUG_TAKEN (ManagementError.TOPIC_SLUG_TAKEN) - code: TOPIC_SLUG_TAKEN category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "같은 slug 의 주제가 이미 있습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — TOPIC_IN_USE (ManagementError.TOPIC_IN_USE) - code: TOPIC_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "이 주제를 쓰는 기록이 있어 삭제할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — PROJECT_NOT_FOUND (ManagementError.PROJECT_NOT_FOUND) - code: PROJECT_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "프로젝트를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — PROJECT_SLUG_TAKEN (ManagementError.PROJECT_SLUG_TAKEN) - code: PROJECT_SLUG_TAKEN category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "같은 slug 의 프로젝트가 이미 있습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — PROJECT_IN_USE (ManagementError.PROJECT_IN_USE) - code: PROJECT_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "이 프로젝트에 연결된 기록이 있어 삭제할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — RELEASE_NOT_FOUND (ManagementError.RELEASE_NOT_FOUND) - code: RELEASE_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "요청한 릴리즈를 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — RELEASE_VERSION_TAKEN (ManagementError.RELEASE_VERSION_TAKEN) - code: RELEASE_VERSION_TAKEN category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "같은 버전의 릴리즈가 이미 있습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — RELEASE_NOT_PUBLISHABLE (ManagementError.RELEASE_NOT_PUBLISHABLE) - code: RELEASE_NOT_PUBLISHABLE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "지금 상태에서는 발행할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — DOCUMENT_PUBLISHED (ManagementError.DOCUMENT_PUBLISHED) - code: DOCUMENT_PUBLISHED category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "공개된 기록은 삭제할 수 없습니다. 먼저 공개를 취소해 주세요" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — QUESTION_NOT_FOUND (ManagementError.QUESTION_NOT_FOUND) - code: QUESTION_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "질문을 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — DOCUMENT_IN_USE (ManagementError.DOCUMENT_IN_USE) - code: DOCUMENT_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "이 기록을 참조하는 곳이 있어 삭제할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — QUESTION_IN_USE (ManagementError.QUESTION_IN_USE) - code: QUESTION_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "이 질문을 참조하는 곳이 있어 삭제할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — DECISION_NOT_FOUND (ManagementError.DECISION_NOT_FOUND) - code: DECISION_NOT_FOUND category: NOT_FOUND http_status: 404 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "결정을 찾을 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest # source: studio-management-v1.yaml ApiError.code — DECISION_IN_USE (ManagementError.DECISION_IN_USE) - code: DECISION_IN_USE category: CONFLICT http_status: 409 retryable: false retry_after_seconds: null owner_branch: feature-techlog-management-v1 owner_layer: application client_safe_message: "이 결정을 참조하는 곳이 있어 삭제할 수 없습니다" log_level: INFO runbook_link: null compatibility_impact: additive required_test: ManagementErrorRegistryTest