infiniflow/ragflow · error · RuntimeError

Unable to determine artifact entry type: {relative_path}

Error message

Unable to determine artifact entry type: {relative_path}

What it means

Raised as RuntimeError during artifact collection when an SFTP directory entry's st_mode is None and a follow-up sftp.lstat() also returns None mode. The provider cannot classify the entry (link/dir/regular) and refuses to guess, because misclassification would bypass the symlink and type guards that follow. This is a defensive guard against pathological SFTP servers rather than a user input error.

Source

Thrown at agent/sandbox/providers/ssh.py:638

        sftp: paramiko.SFTPClient,
        current_dir: str,
        relative_dir: str,
        artifacts: list[dict[str, Any]],
    ) -> None:
        try:
            entries = sftp.listdir_attr(current_dir)
        except FileNotFoundError:
            return

        for entry in sorted(entries, key=lambda item: item.filename):
            name = entry.filename
            remote_path = posixpath.join(current_dir, name)
            relative_path = posixpath.join(relative_dir, name) if relative_dir else name
            mode = entry.st_mode
            if mode is None:
                mode = sftp.lstat(remote_path).st_mode
            if mode is None:
                raise RuntimeError(f"Unable to determine artifact entry type: {relative_path}")

            if stat.S_ISLNK(mode):
                raise RuntimeError(f"Artifact symlinks are not allowed: {relative_path}")
            if stat.S_ISDIR(mode):
                self._collect_artifacts_recursive(sftp, remote_path, relative_path, artifacts)
                continue
            if not stat.S_ISREG(mode):
                raise RuntimeError(f"Unsupported artifact entry: {relative_path}")

            if len(artifacts) >= self.max_artifacts:
                raise RuntimeError(f"SSH execution produced more than {self.max_artifacts} artifacts.")

            size = int(entry.st_size or 0)
            if size > self.max_artifact_bytes:
                raise RuntimeError(f"Artifact exceeds {self.max_artifact_bytes} bytes: {relative_path}")

            ext = os.path.splitext(name)[1].lower()
            if ext not in ALLOWED_ARTIFACT_EXTENSIONS:

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Retry artifact collection once — transient races disappear when the entry is gone or settled
  2. Update/patch the remote SFTP server (OpenSSH) if attrs are consistently missing
  3. Ensure sandboxed code does not delete or mutate its own output directory while execution finishes
Defensive patterns

Strategy: retry

Try / catch

try:
    artifacts = provider.collect_artifacts(instance_id, artifacts_dir)
except RuntimeError as e:
    if "Unable to determine artifact entry type" in str(e):
        time.sleep(1)
        artifacts = provider.collect_artifacts(instance_id, artifacts_dir)
    else:
        raise

Prevention

When it happens

Trigger: Artifact collection on an SFTP server that returns incomplete attrs from listdir_attr and lstat (some embedded/legacy sshd or SFTP wrappers); racing deletion where the entry vanishes between list and lstat; non-POSIX SFTP emulation layers.

Common situations: Running the sandbox against NAS appliances or Windows OpenSSH with unusual attribute support; files being cleaned up concurrently by another process inside the workspace.

Related errors


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