crewAIInc/crewAI · error · ValueError

Either password or private_key_path must be provided

Error message

Either password or private_key_path must be provided

What it means

SnowflakeSearchTool's config model (SnowflakeConfig) enforces in model_post_init that at least one authentication method is present: password or private_key_path. If both are unset, ValueError is raised immediately at configuration time, before any connection attempt. This is a fail-fast guard against ambiguous/absent credentials.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/snowflake_search_tool/snowflake_search_tool.py:63

    )
    user: str = Field(..., description="Snowflake username")
    password: SecretStr | None = Field(None, description="Snowflake password")
    private_key_path: str | None = Field(None, description="Path to private key file")
    warehouse: str | None = Field(None, description="Snowflake warehouse")
    database: str | None = Field(None, description="Default database")
    snowflake_schema: str | None = Field(None, description="Default schema")
    role: str | None = Field(None, description="Snowflake role")
    session_parameters: dict[str, Any] | None = Field(
        default_factory=dict, description="Session parameters"
    )

    @property
    def has_auth(self) -> bool:
        return bool(self.password or self.private_key_path)

    def model_post_init(self, *args: Any, **kwargs: Any) -> None:
        if not self.has_auth:
            raise ValueError("Either password or private_key_path must be provided")


class SnowflakeSearchToolInput(BaseModel):
    """Input schema for SnowflakeSearchTool."""

    model_config = ConfigDict(protected_namespaces=())

    query: str = Field(..., description="SQL query or semantic search query to execute")
    database: str | None = Field(None, description="Override default database")
    snowflake_schema: str | None = Field(None, description="Override default schema")
    timeout: int | None = Field(300, description="Query timeout in seconds")


class SnowflakeSearchTool(BaseTool):
    """Tool for executing queries and semantic search on Snowflake."""

    name: str = "Snowflake Database Search"
    description: str = (

View on GitHub (pinned to 754d7323be)

Solutions

  1. Pass password="..." for password auth, or private_key_path="/path/to/rsa_key.p8" for key-pair auth — exactly one is sufficient.
  2. Check for typos: the field is private_key_path, not private_key_file or key_path.
  3. If credentials come from a vault/secret manager, fetch them before constructing the config object.

Example fix

# before
config = SnowflakeConfig(account="xy123", user="ME")

# after
config = SnowflakeConfig(account="xy123", user="ME", password=os.environ["SNOWFLAKE_PASSWORD"])
Defensive patterns

Strategy: validation

Validate before calling

if not (password or private_key_path):
    raise ValueError("Provide SNOWFLAKE_PASSWORD or SNOWFLAKE_PRIVATE_KEY_PATH")
config = SnowflakeConfig(
    account=account, user=user,
    password=password, private_key_path=private_key_path,
)

Try / catch

try:
    config = SnowflakeConfig(account=a, user=u, password=p, private_key_path=k)
except ValueError as e:
    if "password or private_key_path" in str(e):
        # fetch credentials from vault, then retry construction
        raise

Prevention

When it happens

Trigger: Building SnowflakeConfig/SnowflakeSearchTool with only account and user but neither password nor private_key_path; intending key-pair auth but misspelling private_key_path (e.g. private_key_file); relying on an env var the config does not read.

Common situations: Users assuming SSO/browser auth works because the snowflake connector supports it; typos in the field name for the key path; secrets loaded asynchronously (e.g. from a vault) so the config is constructed before credentials arrive.

Related errors


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