crewAIInc/crewAI · error · ProjectDefinitionError
Invalid project root for [tool.crewai] definition: {exc}
Error message
Invalid project root for [tool.crewai] definition: {exc} What it means
Raised when Path.resolve(strict=True) on the project root raises OSError, meaning the root passed to resolve_project_definition_path does not exist or cannot be stat'd (missing directory, permission denied, broken symlink, or a path component that is a file). The definition path itself has not been evaluated yet; the problem is the root. The original OSError is chained via 'from exc'.
Source
Thrown at lib/crewai-core/src/crewai_core/project.py:119
definition_path = Path(definition)
windows_definition_path = PureWindowsPath(definition)
if definition.startswith("~"):
raise ProjectDefinitionError(
"[tool.crewai] definition must be a project-local path; "
f"got {definition!r}."
)
if definition_path.is_absolute() or windows_definition_path.is_absolute():
raise ProjectDefinitionError(
"[tool.crewai] definition must be relative to the project root; "
f"got {definition!r}."
)
try:
root = root_path.resolve(strict=True)
except OSError as exc:
raise ProjectDefinitionError(
f"Invalid project root for [tool.crewai] definition: {exc}"
) from exc
candidate = root / definition_path
try:
resolved_candidate = candidate.resolve(strict=False)
except OSError as exc:
raise ProjectDefinitionError(
f"Invalid [tool.crewai] definition path {definition!r}: {exc}"
) from exc
if not resolved_candidate.is_relative_to(root):
raise ProjectDefinitionError(
"[tool.crewai] definition must resolve inside the project root; "
f"got {definition!r}."
)
if not resolved_candidate.exists():View on GitHub (pinned to 754d7323be)
Solutions
- Check the project root exists and is a directory before calling the resolver: Path(project_root).is_dir().
- Print or log the exact root value being passed; it usually differs from what you expect in CI or when cwd changed.
- Derive the root from a known anchor (the pyproject.toml location) instead of assuming cwd.
Example fix
# before
root = os.environ.get("CREW_ROOT", "/opt/crew") # may not exist
path = resolve_project_definition_path(definition, root)
# after
root = Path(__file__).resolve().parent.parent # anchor to this file
path = resolve_project_definition_path(definition, root) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def valid_root(project_root: str | Path) -> bool:
p = Path(project_root)
return p.exists() and p.is_dir() and p.resolve(strict=True) is not None Try / catch
try:
path = resolve_project_definition_path(definition, root)
except ProjectDefinitionError as e:
if "Invalid project root" in str(e):
# root problem, not definition problem
... Prevention
- Derive project_root from an anchor file (pyproject.toml location) rather than cwd or env vars.
- Assert the root directory exists at startup, not lazily at first resolution.
When it happens
Trigger: Calling resolve_project_definition_path(definition="main.py", project_root="/nonexistent/dir") or with a root the process cannot read; also when the root contains a symlink loop or the passed root is actually a file path.
Common situations: Hardcoding a root in CI that differs between runners, running from a deleted/renamed working directory, or passing repo-root detection output (e.g. git rev-parse) that returned empty and got joined into an invalid path.
Related errors
- Failed to update OAuth2 settings: {e!s}
- Git is not installed or not found in your PATH.
- An unexpected error occurred: {e}
- An unexpected error occurred while running the JSON crew: {e
- An unexpected error occurred while running the declarative f
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/ec3394c715ae0a0a.
Report an issue: GitHub.