Repository: mlflow/mlflow

Issue:
Cannot preview artifacts in UI when uploaded to remote machine via FTP
### System information
- **Have I written custom code (as opposed to using a stock example script provided in MLflow)**:
No
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:
Linux Ubuntu 18.04
- **MLflow installed from (source or binary)**: 
installed via from pypi via pip
- **MLflow version (run ``mlflow --version``)**:
0.9.1
- **Python version**: 
3.6.7
- **npm version (if running the dev UI):
- **Exact command to reproduce**:
Server runs with:
```
mlflow server --backend-store-uri ./mlruns --default-artifact-root ./artifacts -h 0.0.0.0 -p 5020
```
within a folder holding a `mlruns` and a `artifacts` folder

### Describe the problem
I am running the server on a remote machine.
On the local machine which uploads via the tracking API the
tracking uri is set to: `http://path.to.server:port`
and artifact uri to: `ftp://anonymous:@path.to.server/artifacts`

uploading the tracking information and artifacts work fine and everything shows in the ui:
![image](https://user-images.githubusercontent.com/12450485/58400502-7d0e9e00-805b-11e9-8d4f-b89a1bab5cb1.png)

However when I try to click one of the artifacts I always get the message that something went wrong:
![image](https://user-images.githubusercontent.com/12450485/58400530-99aad600-805b-11e9-8887-4f2640765ba4.png)

Previewing the artifacts work when I store them locally on my machine but as soon as I transfer them via FTP and then try to preview them from the remote machine I get the error shown above.


### Source code / logs
-



Discussion:
Did you check error(trace log) on the server side?
I have faced similar issue #1340  while using s3 as storage when I run sever in a docker container?


> Did you check error(trace log) on the server side?
> I have faced similar issue while using s3 as storage and facing a similar issue when I run sever in a docker container?

Where would I find that? There are no messages being printed to the console. Is mlflow writing to some log file?
```
Error: "Can't find child."
    value ArtifactUtils.js:50
    value ArtifactUtils.js:46
    value ArtifactView.js:190
    value ArtifactView.js:57
    React 9

react-dom.production.min.js:151:111
    React 8

Error: "Can't find child."
    value ArtifactUtils.js:50
    value ArtifactUtils.js:46
    value ArtifactView.js:190
    value ArtifactView.js:57
    React 9

AppErrorBoundary.js:19:4

Unhandled promise rejection TypeError: "c is undefined"
    w Reducers.js:228
    w Reducers.js:227
    Redux 7
    j es6.promise.js:75
    j es6.promise.js:60

    u _microtask.js:18
es6.promise.js:110
```
This is what the firefox console outputs
I was able to fix it with a [dirty hack](https://github.com/kafendt/mlflow/commit/e1a80246af112168bcb6102470e7ffbe65388574).

The problem is that when using a ftp artifact store somehow the shown function in Reducers.js receives the full path on ftp server (In my case `"/artifacts/<runUuid>/artifacts/..."`) but what is needed is only the ... bit above. With the hack I introduced everything works fine but I am certain there is a better fix. Unfortunately this was the first time ever I touched Javascript so I don't really know which would be the best place for fixing this.



@kafendt I had a similar issue with ftp server and absolute path instead of relative ones.
I was using vsftpd, but there is an "issue" with NLST command which returns absolute path... (https://github.com/quarkslab/irma-brain/issues/17, https://stackoverflow.com/questions/5153378/should-nlst-ftp-command-return-records-with-or-without-absolute-paths).
It is working way better with pure-ftpd.

Btw, another issue solving the RETR #919
Thats good to know! Thank you
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I just encountered the ftp preview artifact bug, which i was not able to solve via pure-ftpd. Whats the current status here, will this be solved?
Thanks for your help.

**Update:** workaround for me was, to start the mflow server with postgresql+psycopg2 as backend and the artifacts as NFS mount. This worked and I was able to get the version registry up and running. 

`mlflow server --backend-store-uri 'postgresql+psycopg2://postgres:7av#ision@localhost/postgres' --default-artifact-root /mnt/sharedfolder_client  --host 0.0.0.0
`
Thank you for interacting with this issue! Removing the stale label!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I believe I am having a similar problem and none of the above solutions worked for me.
In my case I'm setting the artifact URI in the `mlflow.create_experiment()` and the tracking URI at `mlflow.set_tracking_uri()`.
For these experiments I have a VM that I can access through SFTP to store the artifacts and I can also access through PostgreSQL to edit a DB file and store the different params and metrics.
The main page of the UI works and I can see a list of all the runs, tags, params and metrics but once I try to see a specific run so I can see a list of the artifacts I get a page with the message "Something went wrong  - If this error persists (...)". The console shows the following error:
`Failed to load resource: the server responded with a status of 500 (INTERNAL SERVER ERROR)
Actions.js:234 XHR failed Object
error @ Actions.js:234
react-dom.production.min.js:151 TypeError: Cannot read property 'getErrorCode' of undefined
    at RunPage.js:63
    at t.value (RequestStateWrapper.js:51)
    at f (react-dom.production.min.js:131)
    at beginWork (react-dom.production.min.js:138)
    at i (react-dom.production.min.js:176)
    at a (react-dom.production.min.js:176)
    at _ (react-dom.production.min.js:182)
    at y (react-dom.production.min.js:181)
    at g (react-dom.production.min.js:181)
    at d (react-dom.production.min.js:180)
wt @ react-dom.production.min.js:151
AppErrorBoundary.js:19 TypeError: Cannot read property 'getErrorCode' of undefined
    at RunPage.js:63
    at t.value (RequestStateWrapper.js:51)
    at f (react-dom.production.min.js:131)
    at beginWork (react-dom.production.min.js:138)
    at i (react-dom.production.min.js:176)
    at a (react-dom.production.min.js:176)
    at _ (react-dom.production.min.js:182)
    at y (react-dom.production.min.js:181)
    at g (react-dom.production.min.js:181)
    at d (react-dom.production.min.js:180)
value @ AppErrorBoundary.js:19
:8000/#/experiments/9/runs/95005cd32eb14fd6a9b521aa77477954:1 Uncaught (in promise) e`
Can someone help me sort this out? Thanks for the help in advance.
Thank you for interacting with this issue! Removing the stale label!

@nuno-chicoria, were you able to `save_artifact` from your client ? Are you sure that your mlflow server is able to access to your sftp server ?
Btw, do you have some stacktraces from server side ? 
Hey @nlaille. I am working with @nuno-chicoria on this. 

We are able to save artifacts on the server.

Here is the server side log, when we try to access a specific run page:
![MicrosoftTeams-image](https://user-images.githubusercontent.com/58782224/70641716-f48dce80-1c35-11ea-8325-1fe69df32903.png)

We have switched from sftp to ftp, and we are running it with pure-ftpd as you suggested, but the problem persists. 

Also we have writing and reading permissions on relevant folders and set the _AllowUserFXP_ to yes on the pure-ftdp.conf file.
@grco-xp I never faced this one.
Have you tried to connect to your ftp from the server on which you have started your mlflow server, using a ftp client or a python interpreter with ftplib to reproduce this issue ?
Could you give me some informations about your ftp configurations so I could reproduce it on my side.



Hi, @nlaille. We were able to solve the problem.
The issue is at `ftp_artifact_repo.py` in the function `list_artifacts()`.
In line 106, the function `ftp.nlst(list_dir)` creates a list that is later used to get the artifacts. The problem is that the first 2 items of this list are "." and "..", bash commands to remain or leave the directory. When MLflow tries to search for these files it returns an error. The fix we found was to change line 108 to `for file_name in artifact_files[2:]:` so it starts the iteration at the firts real file.

Resolving patch:
diff --git a/mlflow/store/artifact/ftp_artifact_repo.py b/mlflow/store/artifact/ftp_artifact_repo.py
--- a/mlflow/store/artifact/ftp_artifact_repo.py
+++ b/mlflow/store/artifact/ftp_artifact_repo.py
@@ -111,6 +111,7 @@ def list_artifacts(self, path=None):
             if not self._is_dir(ftp, list_dir):
                 return []
             artifact_files = ftp.nlst(list_dir)
+            artifact_files = list(filter(lambda x: x != "." and x != "..", artifact_files))
             infos = []
             for file_name in artifact_files:
                 file_path = (file_name if path is None


Test patch: