{"record":{"id":"ae8533493b3c5c80","repo":"crewAIInc/crewAI","slug":"project-name-name-would-generate-invalid-pytho-ae8533","errorCode":null,"errorMessage":"Project name '{name}' would generate invalid Python class name '{class_name}'","messagePattern":"Project name '(.+?)' would generate invalid Python class name '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/cli/src/crewai_cli/create_crew.py","lineNumber":120,"sourceCode":"    if class_name[0].isdigit():\n        raise ValueError(\n            f\"Project name '{name}' would generate class name '{class_name}' which cannot start with a digit\"\n        )\n\n    original_name_clean = re.sub(\n        r\"[^a-zA-Z0-9_]\", \"\", name.replace(\"_\", \"\").replace(\"-\", \"\").lower()\n    )\n    if (\n        keyword.iskeyword(original_name_clean)\n        or keyword.iskeyword(class_name)\n        or class_name in (\"True\", \"False\", \"None\")\n    ):\n        raise ValueError(\n            f\"Project name '{name}' would generate class name '{class_name}' which is a reserved Python keyword\"\n        )\n\n    if not class_name.isidentifier():\n        raise ValueError(\n            f\"Project name '{name}' would generate invalid Python class name '{class_name}'\"\n        )\n\n    if parent_folder:\n        folder_path = Path(parent_folder) / folder_name\n    else:\n        folder_path = Path(folder_name)\n\n    if folder_path.exists():\n        if is_dmn_mode_enabled():\n            raise click.ClickException(f\"Folder {folder_name} already exists.\")\n        if not click.confirm(\n            f\"Folder {folder_name} already exists. Do you want to override it?\"\n        ):\n            click.secho(\"Operation cancelled.\", fg=\"yellow\")\n            sys.exit(0)\n        click.secho(f\"Overriding folder {folder_name}...\", fg=\"green\", bold=True)\n        shutil.rmtree(folder_path)","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/cli/src/crewai_cli/create_crew.py#L102-L138","documentation":"Raised by ContextualRerankTool._run when POST https://api.contextual.ai/v1/rerank returns a non-200 status. The message embeds the HTTP status code and the raw response body, which usually identifies the cause (401 bad API key, 422 invalid model/params, 429 rate limit). Note the surrounding `except Exception` converts this into a 'Failed to rerank documents: ...' string return, so callers see a string, not an exception.","triggerScenarios":"Invalid or missing CONTEXTUAL_API_KEY (401), passing an unknown model name (422), payload too large, or rate limiting (429) from requests.post(rerank_url, json=payload, timeout=30).","commonSituations":"Expired/rotated API key, model name typo (e.g. a deprecated reranker version), bursting many rerank calls, or network egress blocked in containers.","solutions":["Read the embedded status/text in the returned 'Failed to rerank documents: ...' string — it names the exact cause.","401: verify CONTEXTUAL_API_KEY is set, valid, and has rerank access.","422: use a supported model identifier and valid documents/metadata shapes.","429/5xx: add backoff and retry the call after a delay."],"exampleFix":"# before\nout = tool._run(query=q, documents=docs, model='contextual-rerank-v9')  # -> 'Failed to rerank documents: Reranker API returned status 404...'\n# after\nout = tool._run(query=q, documents=docs, model='contextual-rerank-v2')\nif out.startswith('Failed to rerank'):\n    raise RuntimeError(out)  # surface instead of silently treating as content","handlingStrategy":"try-catch","validationCode":"import requests\nresp = requests.get(\"https://api.contextual.ai/v1/datastores\", headers={\"authorization\": f\"Bearer {api_key}\"}, timeout=10)\nif resp.status_code == 401:\n    raise SystemExit(\"CONTEXTUAL_API_KEY is invalid or expired\")","typeGuard":null,"tryCatchPattern":"out = tool._run(query=q, documents=docs, model=model)  # tool returns a string on failure\nif out.startswith(\"Failed to rerank documents:\"):\n    if \"status 429\" in out:\n        time.sleep(30); out = tool._run(query=q, documents=docs, model=model)  # retry once\n    else:\n        raise RuntimeError(out)","preventionTips":["The tool swallows exceptions and returns a 'Failed to rerank documents: ...' string — always string-check the return, don't rely on exceptions.","Validate the API key with a cheap GET before the run.","Use current model identifiers and add rate-limit backoff around rerank calls."],"tags":["contextualai","api","http","rerank"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}