crewAIInc/crewAI · error · ValueError

No deployable project files were found.

Error message

No deployable project files were found.

What it means

Raised by _check_index_exists when scoped_index is false but self.cluster is None. The cluster-level branch needs the cluster handle to call cluster.search_indexes().get_all_indexes(); if the tool was constructed without a cluster connection (e.g. only cluster_string or neither), that handle is missing and the guard fires before any API call.

Source

Thrown at lib/cli/src/crewai_cli/deploy/archive.py:49

    ".env.sample",
}
_EXCLUDED_SUFFIXES = {
    ".pyc",
    ".pyo",
}


def create_project_zip(
    project_name: str,
    *,
    project_dir: Path | None = None,
    repository: git.Repository | None = None,
) -> Path:
    """Create a deployable ZIP archive for a CrewAI project."""
    root = (project_dir or Path.cwd()).resolve()
    files = _project_files(root, repository)
    if not files:
        raise ValueError("No deployable project files were found.")

    staged_root = _stage_project(root, files)
    archive_handle = tempfile.NamedTemporaryFile(
        prefix=f"{project_name}-",
        suffix=".zip",
        delete=False,
    )
    archive_path = Path(archive_handle.name)
    archive_handle.close()

    try:
        with zipfile.ZipFile(archive_path, "w", zipfile.ZIP_DEFLATED) as zip_file:
            for relative_path in _walk_files(staged_root):
                absolute_path = staged_root / relative_path
                zip_file.write(absolute_path, relative_path.as_posix())
    finally:
        shutil.rmtree(staged_root, ignore_errors=True)

View on GitHub (pinned to 754d7323be)

Solutions

  1. Connect first and pass the cluster: cluster = Cluster('couchbase://localhost', authenticator=PasswordAuthenticator(user, pw)); tool = CouchbaseFTSVectorSearchTool(cluster=cluster, ..., scoped_index=False).
  2. Or keep scoped_index=True when you are using connection-string/credential configuration.
  3. Ensure cluster.wait_until_ready(...) completed so the handle is usable.

Example fix

# before
tool = CouchbaseFTSVectorSearchTool(bucket_name='travel', scope_name='inventory', collection_name='hotel', index_name='idx', scoped_index=False)  # ValueError: Cluster instance must be provided
# after
from couchbase.cluster import Cluster
from couchbase.auth import PasswordAuthenticator
cluster = Cluster('couchbase://127.0.0.1', authenticator=PasswordAuthenticator('admin', 'pass'))
tool = CouchbaseFTSVectorSearchTool(cluster=cluster, bucket_name='travel', scope_name='inventory', collection_name='hotel', index_name='idx', scoped_index=False)
Defensive patterns

Strategy: type-guard

Validate before calling

if not scoped_index and cluster is None:
    raise ValueError("scoped_index=False requires a connected cluster instance")
tool = CouchbaseFTSVectorSearchTool(cluster=cluster, scoped_index=scoped_index, ...)

Type guard

from couchbase.cluster import Cluster

def has_cluster(conn: object) -> bool:
    """True when conn is a usable connected Couchbase Cluster."""
    return isinstance(conn, Cluster) and conn is not None

Prevention

When it happens

Trigger: Constructing the tool with scoped_index=False while passing no cluster instance (relying on connection string/credentials that never produced a connected cluster object).

Common situations: Mixing the two init modes — passing cluster_string + credentials (scoped-style config) but setting scoped_index=False, which expects an already-connected Cluster object.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/1e1511113ec2c982. Report an issue: GitHub.