{"record":{"id":"e1f5c4522ef501c4","repo":"infiniflow/ragflow","slug":"invalid-ssh-provider-configuration","errorCode":null,"errorMessage":"Invalid SSH provider configuration.","messagePattern":"Invalid SSH provider configuration\\.","errorType":"exception","errorClass":"SandboxProviderConfigError","httpStatus":null,"severity":"error","filePath":"agent/sandbox/providers/ssh.py","lineNumber":115,"sourceCode":"        is_valid, error_message = self.validate_config(\n            {\n                \"host\": self.host,\n                \"port\": self.port,\n                \"username\": self.username,\n                \"password\": self.password,\n                \"private_key\": self.private_key,\n                \"passphrase\": self.passphrase,\n                \"python_bin\": self.python_bin,\n                \"node_bin\": self.node_bin,\n                \"work_dir\": self.work_dir,\n                \"timeout\": self.timeout,\n                \"max_output_bytes\": self.max_output_bytes,\n                \"max_artifacts\": self.max_artifacts,\n                \"max_artifact_bytes\": self.max_artifact_bytes,\n            }\n        )\n        if not is_valid:\n            raise SandboxProviderConfigError(error_message or \"Invalid SSH provider configuration.\")\n\n        self._assert_connectivity()\n\n        self._initialized = True\n        return True\n\n    def create_instance(self, template: str = \"python\") -> SandboxInstance:\n        if not self._initialized:\n            raise RuntimeError(\"Provider not initialized. Call initialize() first.\")\n\n        language = self._normalize_language(template)\n        client = self._create_ssh_client()\n        sftp = client.open_sftp()\n\n        try:\n            remote_work_dir = self._create_remote_workspace(client)\n            stdout, stderr, exit_code = self._run_remote_command(\n                client,","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/sandbox/providers/ssh.py#L97-L133","documentation":"Raised by SSHProvider.initialize() when validate_config() rejects the assembled config and returns no specific error message. The provider then raises SandboxProviderConfigError with this generic text. validate_config checks the SSH connection parameters (host, port, username, and password/private_key auth material), so this fires when required fields are missing or the auth combination is incomplete — before _assert_connectivity() ever opens a connection.","triggerScenarios":"Calling initialize() with empty 'host' or 'username'; providing neither 'password' nor 'private_key'; passing a port of 0 or a non-numeric port; whitespace-only credential strings after .strip().","commonSituations":"Env vars for SSH credentials unset in the deployment (empty strings); a secrets manager returning None rendered as ''; switching from password auth to key auth and forgetting to populate private_key; config keys misnamed (hostname instead of host).","solutions":["Ensure initialize() config includes non-empty 'host', 'username', and exactly one auth path: 'password' or 'private_key' (with optional 'passphrase').","Validate and fail early in your own code: check required keys before calling initialize() so you can emit which field is missing.","Check the env/secrets source (e.g. SSH_HOST, SSH_USER, SSH_PRIVATE_KEY) is set in the runtime environment.","Confirm key names match the schema in get_config_schema(); a typo'd key silently leaves the field empty."],"exampleFix":"# before\nprovider.initialize({\"host\": \"\", \"username\": \"root\"})\n\n# after\nprovider.initialize({\n    \"host\": \"10.0.0.5\",\n    \"port\": 22,\n    \"username\": \"runner\",\n    \"private_key\": \"-----BEGIN OPENSSH PRIVATE KEY-----...\",\n})","handlingStrategy":"validation","validationCode":"def valid_ssh_config(cfg: dict) -> bool:\n    return bool(\n        str(cfg.get(\"host\", \"\")).strip()\n        and str(cfg.get(\"username\", \"\")).strip()\n        and (cfg.get(\"password\") or cfg.get(\"private_key\"))\n    )\n\nassert valid_ssh_config(config), \"SSH config missing host/username/auth\"","typeGuard":"def has_ssh_auth(cfg: dict) -> bool:\n    \"\"\"True when the config carries exactly one usable SSH auth path.\"\"\"\n    return bool(cfg.get(\"password\")) != bool(cfg.get(\"private_key\"))","tryCatchPattern":"try:\n    provider.initialize(config)\nexcept SandboxProviderConfigError as e:\n    raise ValueError(f\"SSH provider misconfigured: {e}\") from e","preventionTips":["Fail fast in your own code on empty host/username or missing password+key before initialize().","Load SSH credentials from a secrets manager and assert non-empty at startup.","Match config key names to get_config_schema() exactly."],"tags":["sandbox","ssh","configuration","credentials","validation"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}