vllm-project/vllm · error · HTTPException
Key existence check failed: {str(e)}
Error message
Key existence check failed: {str(e)} What it means
HTTP 500 raised when HF3FSMetadataServerState.batch_key_exists(keys) throws while looking up keys in the metadata store. The format check has already passed, so the failure is inside state access — typically unhashable/unserializable key values or internal dict corruption. The original exception is chained via 'from e', and the response detail embeds its str().
Source
Thrown at vllm/distributed/kv_transfer/kv_connector/v1/hf3fs/hf3fs_metadata_server.py:356
except Exception as e:
logger.error("Confirm write for keys failed: %s", e)
raise HTTPException(
status_code=500, detail=f"Confirmation failed: {str(e)}"
) from e
async def batch_key_exists(self, request: Request):
"""Check if multiple keys exist in metadata."""
data = await self._read_json(request)
keys = data.get("keys", [])
if not isinstance(keys, list):
raise HTTPException(status_code=400, detail="Invalid keys format")
try:
exists_results = self.state.batch_key_exists(keys)
return self._json_response({"exists": exists_results})
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Key existence check failed: {str(e)}"
) from e
async def get_key_locations(self, request: Request):
"""Get page indices for keys on a specific rank."""
data = await self._read_json(request)
rank = data.get("rank")
keys = data.get("keys", [])
# Validate input format
if rank is None or not isinstance(keys, list):
raise HTTPException(
status_code=400, detail="Invalid request format: need 'rank' and 'keys'"
)
try:
# Get key locations
locations = self.state.get_key_locations(rank, keys)View on GitHub (pinned to c794754062)
Solutions
- Inspect the '{str(e)}' part of the 500 detail — it is the underlying state-layer exception.
- Ensure all keys are plain hashable values (strings or string-serialized tuples) before sending.
- If the state layer is corrupted, restart the metadata server to rebuild state.
Example fix
// before keys = [["sess", 1], ["sess", 2]] // after keys = ["sess|1", "sess|2"]
Defensive patterns
Strategy: type-guard
Validate before calling
keys = [str(k) for k in keys] # guarantee hashable string keys before POST
Type guard
def all_hashable_keys(keys) -> bool:
return all(isinstance(k, (str, int)) for k in keys) Try / catch
Catch the 500 and surface the embedded str(e) detail; treat as non-retryable state errors and alert — the metadata server state needs attention.
Prevention
- Serialize composite keys to a single string format ('|'.join) client-side
- Never send dicts/lists as key elements
When it happens
Trigger: Passing a list containing non-string/non-hashable elements such as nested lists or dicts as keys; concurrent mutation of the key map while it is being read; corrupted in-memory state after a partial crash.
Common situations: Client builds keys from unhashable data (e.g. lists instead of tuples/strings); mixed-version clients that send structured key objects where plain strings are expected.
Related errors
- Allocation failed: {str(e)}
- Confirmation failed: {str(e)}
- Failed to get key locations: {str(e)}
- Rank {rank} not initialized
- Invalid initialization parameters
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/6143500810124f62.
Report an issue: GitHub.