infiniflow/ragflow · error · RuntimeError
Remote workspace creation did not return a path.
Error message
Remote workspace creation did not return a path.
What it means
Raised as RuntimeError by _create_remote_workspace when the mktemp command exits 0 but stdout contains no path. The provider takes the last non-empty stdout line as the workspace directory; if the remote shell produces no usable output (exotic shell wrappers, output swallowed by a forced command, or stdout consumed by profile scripts), the path is empty and creation is treated as failed.
Source
Thrown at agent/sandbox/providers/ssh.py:529
except Exception as exc:
errors.append(str(exc))
raise SandboxProviderConfigError("Failed to load SSH private key. " + "; ".join(error for error in errors if error))
def _create_remote_workspace(self, client: paramiko.SSHClient) -> str:
base_dir = self.work_dir.rstrip("/") or "/tmp"
template = posixpath.join(base_dir, "ragflow-codeexec.XXXXXX")
stdout, stderr, exit_code = self._run_remote_command(
client,
f"mkdir -p {shlex.quote(base_dir)} && mktemp -d {shlex.quote(template)}",
timeout=min(self.timeout, 10),
)
if exit_code != 0:
raise RuntimeError(f"Failed to create remote workspace on {self.host}: {stderr or stdout or 'unknown error'}")
remote_work_dir = stdout.strip().splitlines()[-1] if stdout.strip() else ""
if not remote_work_dir:
raise RuntimeError("Remote workspace creation did not return a path.")
return remote_work_dir
def _upload_script(
self,
sftp: paramiko.SFTPClient,
remote_work_dir: str,
language: str,
code: str,
args_json: str,
) -> tuple[str, str]:
if language == "python":
script_name = "main.py"
script_content = build_python_wrapper(code, args_json)
elif language in {"javascript", "nodejs"}:
script_name = "main.js"
script_content = build_javascript_wrapper(code, args_json)
else:
raise RuntimeError(f"Unsupported language for SSH provider: {language}")View on GitHub (pinned to 554fb1133a)
Solutions
- Run ssh user@host 'mktemp -d /tmp/ragflow-codeexec.XXXXXX' manually and confirm a path prints on stdout
- Remove stdout-redirecting statements from the account's shell startup files
- Use a plain full-shell account rather than a forced-command wrapper for this provider
Defensive patterns
Strategy: validation
Validate before calling
import subprocess
out = subprocess.run(
["ssh", f"{user}@{host}", f"mktemp -d {work_dir}/x.XXXXXX"],
capture_output=True, text=True,
)
if out.returncode == 0 and not out.stdout.strip():
raise RuntimeError("remote shell swallows stdout; account is unsuitable for this provider") Try / catch
try:
provider.create_instance(language="python")
except RuntimeError as e:
if "did not return a path" in str(e):
log.error("remote account's shell discards stdout; use a plain shell account")
raise Prevention
- Avoid forced-command or output-multiplexing shell wrappers for the sandbox account
- Keep profile scripts from redirecting stdout
- Smoke-test mktemp output over SSH when onboarding a new host
When it happens
Trigger: SSH account whose forced command or shell wrapper discards stdout; login banners/profiles that redirect or consume stdout so mktemp's output never reaches the channel; a remote shell that does not print mktemp results (non-standard busybox wrappers).
Common situations: Bastion accounts with forced command wrappers that multiplex output; shells configured with exec redirects in .profile; extremely minimal embedded systems where mktemp output handling is nonstandard.
Related errors
- Failed to create remote workspace on {self.host}: {stderr or
- Local execution output exceeded {self.max_output_bytes} byte
- Invalid SSH provider configuration.
- Provider not initialized. Call initialize() first.
- Failed to create remote artifacts directory: {stderr or stdo
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/5423c59700521c1f.
Report an issue: GitHub.