{"record":{"id":"93fd67092774bb84","repo":"BerriAI/litellm","slug":"invalid-key-format","errorCode":null,"errorMessage":"Invalid key format.","messagePattern":"Invalid key format\\.","errorType":"http","errorClass":"ProxyException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/management_endpoints/key_management_endpoints.py","lineNumber":6230,"sourceCode":"    Note: This is an admin-only endpoint. Only proxy admins, team admins, or org admins can block keys.\n    \"\"\"\n    from litellm.proxy.management_helpers.audit_logs import (\n        get_audit_log_changed_by,\n    )\n    from litellm.proxy.proxy_server import (\n        create_audit_log_for_update,\n        hash_token,\n        litellm_proxy_admin_name,\n        prisma_client,\n        proxy_logging_obj,\n        user_api_key_cache,\n    )\n\n    if prisma_client is None:\n        raise Exception(f\"{CommonProxyErrors.db_not_connected_error.value}\")\n\n    if not is_valid_api_key(data.key):\n        raise ProxyException(\n            message=\"Invalid key format.\",\n            type=ProxyErrorTypes.bad_request_error,\n            param=\"key\",\n            code=status.HTTP_400_BAD_REQUEST,\n        )\n    if data.key.startswith(\"sk-\"):\n        hashed_token = hash_token(token=data.key)\n    else:\n        hashed_token = data.key\n\n    # Admin-only: only proxy admins, team admins, or org admins can block keys\n    await _check_key_admin_access(\n        user_api_key_dict=user_api_key_dict,\n        hashed_token=hashed_token,\n        prisma_client=prisma_client,\n        user_api_key_cache=user_api_key_cache,\n        route=\"/key/block\",\n    )","sourceCodeStart":6212,"sourceCodeEnd":6248,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/key_management_endpoints.py#L6212-L6248","documentation":"POST /key/block validates data.key with is_valid_api_key before touching the database. A valid value is either a raw 'sk-...' key matching ^sk-[A-Za-z0-9_-]+$ or an already-hashed 64-character hex token ^[a-fA-F0-9]{64}$, with total length between 3 and 100. Anything else (empty string, keys with dots/slashes, other prefixes like 'pk-') gets a 400 ProxyException with param='key'.","triggerScenarios":"Sending 'pk-...' or other non-sk- prefixed strings (which are then assumed to be hashes and fail the 64-hex check); sending the hashed token with uppercase HEX beyond a-f (invalid hex); sending keys containing '.', ':', or whitespace; sending a truncated hash.","commonSituations":"Copy-paste truncation of long hashes; mixing up LiteLLM virtual keys with provider keys of a different prefix; passing the key_alias or key display name instead of the actual token; form inputs that trim/alter characters.","solutions":["Send the raw key exactly as returned at creation time ('sk-' followed by [A-Za-z0-9_-] only)","Or send the 64-character lowercase/uppercase hex hash (the 'token' field from /key/list) — never a partially copied one","Do not send aliases, display names, or other providers' key formats to /key/block","Check for invisible characters if a visually correct key still fails: printf '%s' \"$KEY\" | wc -c must equal the expected length"],"exampleFix":"# before\nawait client.post('/key/block', json={'key': 'pk-live-abc123'})          # 400: Invalid key format.\n# after\nawait client.post('/key/block', json={'key': 'sk-XyZ_123-abc'})            # raw key (hashed server-side)\n# or\nawait client.post('/key/block', json={'key': key_row['token']})           # 64-hex hash from /key/list","handlingStrategy":"type-guard","validationCode":"import re\n\nRAW_KEY_RE = re.compile(r'^sk-[A-Za-z0-9_-]+$')\nHASH_RE = re.compile(r'^[a-fA-F0-9]{64}$')\n\ndef is_blockable_key(key: str) -> bool:\n    \"\"\"Mirror of litellm.proxy.utils.is_valid_api_key.\"\"\"\n    return isinstance(key, str) and 3 <= len(key) <= 100 and bool(\n        RAW_KEY_RE.match(key) or HASH_RE.match(key)\n    )","typeGuard":"from typing import TypeGuard\n\ndef is_blockable_key(key: object) -> TypeGuard[str]:\n    return (\n        isinstance(key, str)\n        and 3 <= len(key) <= 100\n        and bool(RAW_KEY_RE.match(key) or HASH_RE.match(key))\n    )","tryCatchPattern":"if not is_blockable_key(tok):\n    raise ValueError(f'refusing to call /key/block with malformed key: {tok[:6]}...')\ntry:\n    await client.post('/key/block', json={'key': tok})\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 400 and 'Invalid key format' in e.response.text:\n        raise ValueError('key format rejected by server') from e\n    raise","preventionTips":["Never derive the value — use the token returned by /key/generate or /key/list verbatim","Store keys in secrets managers, not config files that may alter characters","Checksum the length client-side: raw sk- keys and 64-hex hashes have predictable shapes"],"tags":["keys","validation","format","litellm-proxy","block"],"backgroundTag":"invalid-api-key-format","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}