{"record":{"id":"bf7e51b4d77468d7","repo":"crewAIInc/crewAI","slug":"project-name-cannot-be-empty-or-contain-only-white","errorCode":null,"errorMessage":"Project name cannot be empty or contain only whitespace","messagePattern":"Project name cannot be empty or contain only whitespace","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/cli/src/crewai_cli/create_crew.py","lineNumber":55,"sourceCode":"    template_content = template_content.replace(\"{{name}}\", \"placeholder\")\n    template_content = template_content.replace(\"{{crew_name}}\", \"Placeholder\")\n\n    template_data = tomli.loads(template_content)\n    script_names = set(template_data.get(\"project\", {}).get(\"scripts\", {}).keys())\n    script_names.discard(\"_placeholder_\")\n    return script_names\n\n\ndef create_folder_structure(\n    name: str, parent_folder: str | None = None\n) -> tuple[Path, str, str]:\n    import keyword\n    import re\n\n    name = name.rstrip(\"/\")\n\n    if not name.strip():\n        raise ValueError(\"Project name cannot be empty or contain only whitespace\")\n\n    folder_name = name.replace(\" \", \"_\").replace(\"-\", \"_\").lower()\n    folder_name = re.sub(r\"[^a-zA-Z0-9_]\", \"\", folder_name)\n\n    if re.match(r\"^[^a-zA-Z0-9_-]+\", name):\n        raise ValueError(\n            f\"Project name '{name}' contains no valid characters for a Python module name\"\n        )\n\n    if not folder_name:\n        raise ValueError(\n            f\"Project name '{name}' contains no valid characters for a Python module name\"\n        )\n\n    if folder_name[0].isdigit():\n        raise ValueError(\n            f\"Project name '{name}' would generate folder name '{folder_name}' which cannot start with a digit (invalid Python module name)\"\n        )","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/cli/src/crewai_cli/create_crew.py#L37-L73","documentation":"Raised as HTTP 401 by APIKeyServerAuth when the presented API key does not byte-equal the key configured on the server. The server stores the key as a SecretStr and compares the raw token string; any mismatch (wrong key, whitespace, encoding) rejects the request.","triggerScenarios":"Calling an A2A endpoint protected by APIKeyServerAuth(api_key=SecretStr(...)) with a token that differs from the configured value: wrong environment's key, key rotated on the server but not the client, key copied with leading/trailing whitespace or quotes, or key sent via the wrong header name.","commonSituations":"Separate staging/production keys mixed up in .env files; key rotated during incident response; CI secret injected with a trailing newline; API key configured with quotes included in the value.","solutions":["Confirm the exact key value on both sides: compare os.environ value hashes rather than eyeballing, and strip whitespace when loading (os.environ['API_KEY'].strip())","Check the key belongs to the same environment (staging key against prod server fails)","After a key rotation, update the client's configured key and restart the process so cached configs reload","Verify the client sends the key in the header scheme the server expects (e.g. X-API-Key vs Authorization), since a missing/misplaced key can surface as this 401"],"exampleFix":"# before\nAPIKeyServerAuth(api_key=SecretStr('\"abc123\"'))  # quotes kept in value\n\n# after\nAPIKeyServerAuth(api_key=SecretStr(os.environ['A2A_API_KEY'].strip()))","handlingStrategy":"validation","validationCode":"import os\n\ndef load_api_key() -> str:\n    key = os.environ.get(\"A2A_API_KEY\", \"\").strip()\n    if not key or key.startswith(('\"', \"'\")):\n        raise RuntimeError(\"A2A_API_KEY unset, empty, or includes quote characters\")\n    return key","typeGuard":null,"tryCatchPattern":"from fastapi import HTTPException\n\ntry:\n    user = await scheme.authenticate(request)\nexcept HTTPException as e:\n    if e.status_code == 401:\n        log_and_alert(\"API key rejected — verify key rotation on both sides\")\n    raise","preventionTips":["Strip whitespace and reject quote characters when loading keys from env or config files","Namespace keys per environment (A2A_API_KEY_STAGING vs A2A_API_KEY_PROD) to prevent cross-env mixups","Coordinate rotations: deploy the new key to clients before (or atomically with) the server change","Compare key presence with a hash (e.g. sha256) when debugging instead of printing secrets"],"tags":["api-key","authentication","a2a","http-401"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}