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

  1. Run ssh user@host 'mktemp -d /tmp/ragflow-codeexec.XXXXXX' manually and confirm a path prints on stdout
  2. Remove stdout-redirecting statements from the account's shell startup files
  3. 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

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


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/5423c59700521c1f. Report an issue: GitHub.