diff --git a/docs/.DS_Store b/docs/.DS_Store
index 560ae6fbf457a39fcfc8c2f24862414f0648c4c3..efcf6d48ca6cbe1f32bb3708f624e8a39f3a1ada 100644
Binary files a/docs/.DS_Store and b/docs/.DS_Store differ
diff --git a/gui/package.json b/gui/package.json
index a13d638e39d008ccea91741f198347b6e2b0c2ac..b59efaf9ba76643868ac3ada3c895ad2bfa4237a 100644
--- a/gui/package.json
+++ b/gui/package.json
@@ -35,6 +35,7 @@
     "eslint": "^4.19.1",
     "eslint-config-standard": "^11.0.0",
     "eslint-plugin-import": "^2.14.0",
+    "eslint-plugin-node": "^8.0.1",
     "eslint-plugin-promise": "^3.7.0",
     "eslint-plugin-react": "^7.11.1",
     "eslint-plugin-standard": "^3.1.0",
diff --git a/gui/src/api.js b/gui/src/api.js
index 9b33b4474e11d4ad0fa013d8b566376befa4093b..45cdab8ca3b2c8dd50a7e90f36e210bd7731d8c8 100644
--- a/gui/src/api.js
+++ b/gui/src/api.js
@@ -18,31 +18,47 @@ const swaggerPromise = Swagger(`${apiBase}/swagger.json`, {
   }
 })
 
-const networkError = (e) => {
-  console.log(e)
-  throw Error('Network related error, cannot reach API: ' + e)
-}
-
-const handleJsonErrors = (e) => {
-  console.log(e)
-  throw Error('API return unexpected data format.')
+export class DoesNotExist extends Error {
+  constructor(msg) {
+    super(msg)
+    this.name = 'DoesNotExist'
+  }
 }
 
-const handleResponseErrors = (response) => {
-  if (!response.ok) {
-    return response.json()
-      .catch(() => {
-        throw Error(`API error (${response.status}): ${response.statusText}`)
-      }).then(data => {
-        throw Error(`API error (${response.status}): ${data.message}`)
-      })
+const handleApiError = (e) => {
+  if (e.response) {
+    const body = e.response.body
+    const message = (body && body.message) ? body.message : e.response.statusText
+    if (e.response.status === 404) {
+      throw new DoesNotExist(message)
+    } else {
+      throw Error(`API error (${e.response.status}): ${message}`)
+    }
+  } else {
+    throw Error('Network related error, cannot reach API: ' + e)
   }
-  return response
 }
 
+const upload_to_gui_ids = {}
+let gui_upload_id_counter = 0
+
 class Upload {
   constructor(json) {
-    this.uploading = 0
+    // Cannot use upload_id as key in GUI, because uploads don't have an upload_id
+    // before upload is completed
+    if (json.upload_id) {
+      // instance from the API
+      this.gui_upload_id = upload_to_gui_ids[json.upload_id]
+      if (this.gui_upload_id === undefined) {
+        // never seen in the GUI, needs a GUI id
+        this.gui_upload_id = gui_upload_id_counter++
+        upload_to_gui_ids[json.upload_id] = this.gui_upload_id
+        console.log('new gui ui')
+      }
+    } else {
+      // new instance, not from the API
+      this.gui_upload_id = gui_upload_id_counter++
+    }
     Object.assign(this, json)
   }
 
@@ -65,13 +81,14 @@ class Upload {
         }
       )
       if (uploadRequest.error) {
-        networkError(uploadRequest.error)
+        handleApiError(uploadRequest.error)
       }
       if (uploadRequest.aborted) {
         throw Error('User abort')
       }
       this.uploading = 100
       this.upload_id = uploadRequest.response.upload_id
+      upload_to_gui_ids[this.upload_id] = this.gui_upload_id
     }
 
     return uploadFileWithProgress()
@@ -84,14 +101,13 @@ class Upload {
     } else {
       if (this.upload_id) {
         return swaggerPromise.then(client => client.apis.uploads.get_upload({
-            upload_id: this.upload_id,
-            page: page || 1,
-            per_page: perPage || 5,
-            order_by: orderBy || 'mainfile',
-            order: order || -1
-          }))
-          .catch(networkError)
-          .then(handleResponseErrors)
+          upload_id: this.upload_id,
+          page: page || 1,
+          per_page: perPage || 5,
+          order_by: orderBy || 'mainfile',
+          order: order || -1
+        }))
+          .catch(handleApiError)
           .then(response => response.body)
           .then(uploadJson => {
             Object.assign(this, uploadJson)
@@ -107,7 +123,7 @@ class Upload {
 function createUpload(name) {
   return new Upload({
     name: name,
-    tasks: ['uploading'],
+    tasks: ['uploading', 'extract', 'parse_all', 'cleanup'],
     current_task: 'uploading',
     uploading: 0,
     create_time: new Date()
@@ -117,8 +133,7 @@ function createUpload(name) {
 async function getUploads() {
   const client = await swaggerPromise
   return client.apis.uploads.get_uploads()
-    .catch(networkError)
-    .then(handleResponseErrors)
+    .catch(handleApiError)
     .then(response => response.body.map(uploadJson => {
       const upload = new Upload(uploadJson)
       upload.uploading = 100
@@ -129,11 +144,10 @@ async function getUploads() {
 async function archive(uploadId, calcId) {
   const client = await swaggerPromise
   return client.apis.archive.get_archive_calc({
-      upload_id: uploadId,
-      calc_id: calcId
-    })
-    .catch(networkError)
-    .then(handleResponseErrors)
+    upload_id: uploadId,
+    calc_id: calcId
+  })
+    .catch(handleApiError)
     .then(response => response.body)
 }
 
@@ -143,61 +157,47 @@ async function calcProcLog(uploadId, calcId) {
     upload_id: uploadId,
     calc_id: calcId
   })
-    .catch(networkError)
-    .then(response => {
-      if (!response.ok) {
-        if (response.status === 404) {
-          return ''
-        } else {
-          return handleResponseErrors(response)
-        }
-      } else {
-        return response.text
-      }
-    })
+    .catch(handleApiError)
+    .then(response => response.text)
 }
 
 async function repo(uploadId, calcId) {
   const client = await swaggerPromise
   return client.apis.repo.get_repo_calc({
-      upload_id: uploadId,
-      calc_id: calcId
-    })
-    .catch(networkError)
-    .then(handleResponseErrors)
+    upload_id: uploadId,
+    calc_id: calcId
+  })
+    .catch(handleApiError)
     .then(response => response.body)
 }
 
 async function repoAll(page, perPage, owner) {
   const client = await swaggerPromise
   return client.apis.repo.get_calcs({
-      page: page,
-      per_page: perPage,
-      ower: owner || 'all'
-    })
-    .catch(networkError)
-    .then(handleResponseErrors)
+    page: page,
+    per_page: perPage,
+    ower: owner || 'all'
+  })
+    .catch(handleApiError)
     .then(response => response.body)
 }
 
 async function deleteUpload(uploadId) {
   const client = await swaggerPromise
   return client.apis.uploads.delete_upload({upload_id: uploadId})
-    .catch(networkError)
-    .then(handleResponseErrors)
+    .catch(handleApiError)
     .then(response => response.body)
 }
 
 async function commitUpload(uploadId) {
   const client = await swaggerPromise
   return client.apis.uploads.exec_upload_command({
-      upload_id: uploadId,
-      payload: {
-        operation: 'commit'
-      }
-    })
-    .catch(networkError)
-    .then(handleResponseErrors)
+    upload_id: uploadId,
+    payload: {
+      operation: 'commit'
+    }
+  })
+    .catch(handleApiError)
     .then(response => response.body)
 }
 
@@ -208,11 +208,11 @@ async function getMetaInfo() {
     return cachedMetaInfo
   } else {
     const loadMetaInfo = async(path) => {
-      return fetch(`${apiBase}/archive/metainfo/${path}`)
-        .catch(networkError)
-        .then(handleResponseErrors)
-        .then(response => response.json())
-        .catch(handleJsonErrors)
+      const client = await swaggerPromise
+      console.log(path)
+      return client.apis.archive.get_metainfo({metainfo_path: path})
+        .catch(handleApiError)
+        .then(response => response.body)
         .then(data => {
           if (!cachedMetaInfo) {
             cachedMetaInfo = {
@@ -243,8 +243,7 @@ async function getMetaInfo() {
 async function getUploadCommand() {
   const client = await swaggerPromise
   return client.apis.uploads.get_upload_command()
-    .catch(networkError)
-    .then(handleResponseErrors)
+    .catch(handleApiError)
     .then(response => response.body.upload_command)
 }
 
diff --git a/gui/src/components/Upload.js b/gui/src/components/Upload.js
index cb8b261961bf52e4d557bbfb2100fc9020d39079..c9462d57c8cd7fb8b70348287f679931cf53b0df 100644
--- a/gui/src/components/Upload.js
+++ b/gui/src/components/Upload.js
@@ -20,7 +20,8 @@ class Upload extends React.Component {
     raiseError: PropTypes.func.isRequired,
     upload: PropTypes.object.isRequired,
     checked: PropTypes.bool,
-    onCheckboxChanged: PropTypes.func
+    onCheckboxChanged: PropTypes.func,
+    onDoesNotExist: PropTypes.func
   }
 
   static styles = theme => ({
@@ -77,7 +78,7 @@ class Upload extends React.Component {
     params: {
       page: 1,
       perPage: 5,
-      orderBy: 'status',
+      orderBy: 'tasks_status',
       order: 'asc'
     },
     archiveLogs: null, // { uploadId, calcId } ids of archive to show logs for
@@ -96,8 +97,9 @@ class Upload extends React.Component {
     this.setState({loading: true})
     this.state.upload.get(page, perPage, orderBy, order === 'asc' ? 1 : -1)
       .then(upload => {
+        const {tasks_running, process_running, current_task} = upload
         if (!this._unmounted) {
-          const continueUpdating = upload.status !== 'SUCCESS' && upload.status !== 'FAILURE' && !upload.is_stale
+          const continueUpdating = tasks_running || process_running || current_task === 'uploading'
           this.setState({upload: upload, loading: false, params: params, updating: continueUpdating})
           if (continueUpdating) {
             window.setTimeout(() => {
@@ -111,7 +113,11 @@ class Upload extends React.Component {
       .catch(error => {
         if (!this._unmounted) {
           this.setState({loading: false, ...params})
-          this.props.raiseError(error)
+          if (error.name === 'DoesNotExist') {
+            this.props.onDoesNotExist()
+          } else {
+            this.props.raiseError(error)
+          }
         }
       })
   }
@@ -120,6 +126,12 @@ class Upload extends React.Component {
     this.update(this.state.params)
   }
 
+  componentDidUpdate(prevProps) {
+    if (!prevProps.upload.process_running && this.props.upload.process_running) {
+      this.update(this.state.params)
+    }
+  }
+
   componentWillUnmount() {
     this._unmounted = true
   }
@@ -169,73 +181,119 @@ class Upload extends React.Component {
   renderStepper() {
     const { classes } = this.props
     const { upload } = this.state
-    const { calcs, tasks, current_task, status, errors } = upload
-
-    let activeStep = tasks.indexOf(current_task)
-    activeStep += (status === 'SUCCESS') ? 1 : 0
+    const { calcs, tasks, current_task, tasks_running, tasks_status, process_running, current_process, errors } = upload
+
+    // map tasks [ uploading, extracting, parse_all, cleanup ] to steps
+    const steps = [ 'upload', 'process', 'commit' ]
+    let step = null
+    const task_index = tasks.indexOf(current_task)
+    if (task_index === 0) {
+      step = 'upload'
+    } else if (task_index > 0 && tasks_running) {
+      step = 'process'
+    } else {
+      step = 'commit'
+    }
+    const stepIndex = steps.indexOf(step)
 
     const labelPropsFactories = {
-      uploading: (props) => {
-        props.children = 'uploading'
-        const { uploading } = upload
-        if (upload.status !== 'FAILURE') {
-          props.optional = (
-            <Typography variant="caption">
-              {uploading === 100  && current_task === tasks[0] ? 'waiting for processing ...' : `${uploading || 0}%`}
-            </Typography>
-          )
+      upload: (props) => {
+        if (step === 'upload') {
+          props.children = 'uploading'
+          const { uploading } = upload
+          if (upload.tasks_status !== 'FAILURE') {
+            props.optional = (
+              <Typography variant="caption">
+                {`${uploading || 0}%`}
+              </Typography>
+            )
+          }
+        } else {
+          props.children = 'uploaded'
         }
       },
-      extracting: (props) => {
-        props.children = 'extracting'
+      process: (props) => {
+        props.error = tasks_status === 'FAILURE'
+
+        const processIndex = steps.indexOf('process')
+        if (stepIndex <= processIndex) {
+          props.children = 'processing'
+        } else {
+          props.children = 'processed'
+        }
+
         if (current_task === 'extracting') {
+          props.children = 'extracting'
           props.optional = (
             <Typography variant="caption">
               be patient
             </Typography>
           )
+        } else if (current_task === 'parse_all') {
+          props.children = 'parsing'
         }
-      },
-      parse_all: (props) => {
-        props.children = 'parse'
-        if (!calcs) {
-          props.optional = (
-            <Typography variant="caption" >
-              loading...
-            </Typography>
-          )
-        } else if (calcs.pagination.total > 0) {
-          const { total, successes, failures } = calcs.pagination
 
-          if (failures) {
-            props.error = true
+        if (stepIndex >= processIndex) {
+          if (!calcs) {
             props.optional = (
-              <Typography variant="caption" color="error">
-                {successes + failures}/{total}, {failures} failed
+              <Typography variant="caption" >
+                matching...
               </Typography>
             )
-          } else {
+          } else if (calcs.pagination.total > 0) {
+            const { total, successes, failures } = calcs.pagination
+            if (failures) {
+              props.error = true
+              props.optional = (
+                <Typography variant="caption" color="error">
+                  {successes + failures}/{total}, {failures} failed
+                </Typography>
+              )
+            } else {
+              props.optional = (
+                <Typography variant="caption">
+                  {successes + failures}/{total}
+                </Typography>
+              )
+            }
+          } else if (tasks_status === 'SUCCESS') {
+            props.error = true
             props.optional = (
-              <Typography variant="caption">
-                {successes + failures}/{total}
-              </Typography>
+              <Typography variant="caption" color="error">No calculations found.</Typography>
             )
           }
-        } else if (status === 'SUCCESS') {
-          props.error = true
+        }
+
+        if (tasks_status === 'FAILURE') {
           props.optional = (
-            <Typography variant="caption" color="error">No calculations found.</Typography>
+            <Typography variant="caption" color="error">
+              {errors.join(' ')}
+            </Typography>
           )
         }
+      },
+      commit: (props) => {
+        props.children = 'inspect'
+
+        if (process_running) {
+          if (current_process === 'commit_upload') {
+            props.children = 'approved'
+            props.optional = <Typography variant="caption">moving data ...</Typography>
+          } else if (current_process === 'delete_upload') {
+            props.children = 'declined'
+            props.optional = <Typography variant="caption">deleting data ...</Typography>
+          }
+        } else {
+          props.optional = <Typography variant="caption">commit or delete</Typography>
+        }
       }
     }
 
     return (
-      <Stepper activeStep={activeStep} classes={{root: classes.stepper}}>
-        {tasks.map((label, index) => {
+      <Stepper activeStep={steps.indexOf(step)} classes={{root: classes.stepper}}>
+        {steps.map((label, index) => {
           const labelProps = {
-            children: label,
-            error: activeStep === index && status === 'FAILURE'
+            children: label
           }
 
           const labelPropsFactory = labelPropsFactories[label]
@@ -243,14 +301,6 @@ class Upload extends React.Component {
             labelPropsFactory(labelProps)
           }
 
-          if (labelProps.error && status === 'FAILURE') {
-            labelProps.optional = (
-              <Typography variant="caption" color="error">
-                {errors.join(' ')}
-              </Typography>
-            )
-          }
-
           return (
             <Step key={label}>
               <StepLabel {...labelProps} />
@@ -264,14 +314,14 @@ class Upload extends React.Component {
   renderCalcTable() {
     const { classes } = this.props
     const { page, perPage, orderBy, order } = this.state.params
-    const { calcs, status, waiting } = this.state.upload
+    const { calcs, tasks_status, waiting } = this.state.upload
     const { pagination, results } = calcs
 
     if (pagination.total === 0) {
-      if (this.state.upload.completed) {
+      if (!this.state.upload.tasks_running) {
         return (
           <Typography className={classes.detailsContent}>
-            {status === 'SUCCESS' ? 'No calculcations found.' : 'No calculations to show.'}
+            {tasks_status === 'SUCCESS' ? 'No calculcations found.' : 'No calculations to show.'}
           </Typography>
         )
       } else {
@@ -292,8 +342,8 @@ class Upload extends React.Component {
     }
 
     const renderRow = (calc, index) => {
-      const { mainfile, calc_id, upload_id, parser, tasks, current_task, status, errors } = calc
-      const color = status === 'FAILURE' ? 'error' : 'default'
+      const { mainfile, calc_id, upload_id, parser, tasks, current_task, tasks_status, errors } = calc
+      const color = tasks_status === 'FAILURE' ? 'error' : 'default'
       const row = (
         <TableRow key={index}>
           <TableCell>
@@ -322,22 +372,20 @@ class Upload extends React.Component {
           </TableCell>
           <TableCell>
             <Typography color={color}>
-              {(status === 'SUCCESS' || status === 'FAILURE')
-                ?
-                  <a className={classes.logLink} href="#logs" onClick={() => this.setState({archiveLogs: { uploadId: upload_id, calcId: calc_id }})}>
-                  {status.toLowerCase()}
-                  </a>
-                : status.toLowerCase()
+              {(tasks_status === 'SUCCESS' || tasks_status === 'FAILURE')
+                ? <a className={classes.logLink} href="#logs" onClick={() => this.setState({archiveLogs: { uploadId: upload_id, calcId: calc_id }})}>
+                  {tasks_status.toLowerCase()}
+                </a> : tasks_status.toLowerCase()
               }
             </Typography>
           </TableCell>
           <TableCell>
-            <CalcLinks uploadId={upload_id} calcId={calc_id} disabled={status !== 'SUCCESS'} />
+            <CalcLinks uploadId={upload_id} calcId={calc_id} disabled={tasks_status !== 'SUCCESS'} />
           </TableCell>
         </TableRow>
       )
 
-      if (status === 'FAILURE') {
+      if (tasks_status === 'FAILURE') {
         return (
           <Tooltip key={calc_id} title={errors.map((error, index) => (<p key={`${calc_id}-${index}`}>{error}</p>))}>
             {row}
@@ -355,7 +403,7 @@ class Upload extends React.Component {
       { id: 'mainfile', sort: true, label: 'mainfile' },
       { id: 'parser', sort: true, label: 'code' },
       { id: 'task', sort: false, label: 'task' },
-      { id: 'status', sort: true, label: 'status' },
+      { id: 'tasks_status', sort: true, label: 'status' },
       { id: 'links', sort: false, label: 'links' }
     ]
 
@@ -434,7 +482,7 @@ class Upload extends React.Component {
           <ExpansionPanel>
             <ExpansionPanelSummary
               expandIcon={<ExpandMoreIcon/>} classes={{root: classes.summary}}>
-              {!(upload.completed || upload.waiting)
+              {(upload.tasks_running || upload.process_running)
                 ? <div className={classes.progress}>
                   <CircularProgress size={32}/>
                 </div>
diff --git a/gui/src/components/Uploads.js b/gui/src/components/Uploads.js
index bc44b2733ff5f89be6cfbc70283c64ea412f9448..b87cbdebfc8f3e5037326dcac9aa17b38194a5fd 100644
--- a/gui/src/components/Uploads.js
+++ b/gui/src/components/Uploads.js
@@ -119,6 +119,17 @@ class Uploads extends React.Component {
       })
   }
 
+  sortedUploads() {
+    return this.state.uploads.concat()
+      .sort((a, b) => (a.gui_upload_id === b.gui_upload_id) ? 0 : ((a.gui_upload_id < b.gui_upload_id) ? -1 : 1))
+  }
+
+  handleDoesNotExist(nonExistingUupload) {
+    this.setState({
+      uploads: this.state.uploads.filter(upload => upload !== nonExistingUupload)
+    })
+  }
+
   onDrop(files) {
     files.forEach(file => {
       const upload = api.createUpload(file.name)
@@ -139,7 +150,7 @@ class Uploads extends React.Component {
 
   onSelectionAllChanged(checked) {
     if (checked) {
-      this.setState({selectedUploads: [...this.state.uploads.filter(upload => upload.completed)]})
+      this.setState({selectedUploads: [...this.state.uploads.filter(upload => !upload.tasks_running)]})
     } else {
       this.setState({selectedUploads: []})
     }
@@ -181,9 +192,10 @@ class Uploads extends React.Component {
             </FormGroup>
           </div>
           <div className={classes.uploads}>
-            {this.state.uploads.map((upload) => (
-              <Upload key={upload.upload_id} upload={upload}
+            {this.sortedUploads().map(upload => (
+              <Upload key={upload.gui_upload_id} upload={upload}
                 checked={selectedUploads.indexOf(upload) !== -1}
+                onDoesNotExist={() => this.handleDoesNotExist(upload)}
                 onCheckboxChanged={checked => this.onSelectionChanged(upload, checked)}/>
             ))}
           </div>
diff --git a/gui/yarn.lock b/gui/yarn.lock
index a9a7488e76af6fafc8ed785b2993ba874e196770..093f3836afa8d753f3821f1fa95db8f00f60a296 100644
--- a/gui/yarn.lock
+++ b/gui/yarn.lock
@@ -2660,6 +2660,13 @@ eslint-module-utils@^2.1.1, eslint-module-utils@^2.2.0:
     debug "^2.6.8"
     pkg-dir "^1.0.0"
 
+eslint-plugin-es@^1.3.1:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6"
+  dependencies:
+    eslint-utils "^1.3.0"
+    regexpp "^2.0.1"
+
 eslint-plugin-flowtype@2.39.1:
   version "2.39.1"
   resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.39.1.tgz#b5624622a0388bcd969f4351131232dcb9649cd5"
@@ -2708,6 +2715,17 @@ eslint-plugin-jsx-a11y@5.1.1:
     emoji-regex "^6.1.0"
     jsx-ast-utils "^1.4.0"
 
+eslint-plugin-node@^8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz#55ae3560022863d141fa7a11799532340a685964"
+  dependencies:
+    eslint-plugin-es "^1.3.1"
+    eslint-utils "^1.3.1"
+    ignore "^5.0.2"
+    minimatch "^3.0.4"
+    resolve "^1.8.1"
+    semver "^5.5.0"
+
 eslint-plugin-promise@^3.7.0:
   version "3.8.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621"
@@ -2749,6 +2767,10 @@ eslint-scope@^3.7.1:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
+eslint-utils@^1.3.0, eslint-utils@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
+
 eslint-visitor-keys@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
@@ -3823,6 +3845,10 @@ ignore@^3.3.3:
   version "3.3.10"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
 
+ignore@^5.0.2:
+  version "5.0.4"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45"
+
 import-lazy@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
@@ -5654,7 +5680,7 @@ path-key@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
 
-path-parse@^1.0.5:
+path-parse@^1.0.5, path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
 
@@ -6570,6 +6596,10 @@ regexpp@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab"
 
+regexpp@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
+
 regexpu-core@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
@@ -6734,6 +6764,12 @@ resolve@^1.3.2, resolve@^1.5.0, resolve@^1.6.0:
   dependencies:
     path-parse "^1.0.5"
 
+resolve@^1.8.1:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06"
+  dependencies:
+    path-parse "^1.0.6"
+
 restore-cursor@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@@ -6848,6 +6884,10 @@ semver-diff@^2.0.0:
   version "5.5.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
 
+semver@^5.5.0:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
+
 send@0.16.2:
   version "0.16.2"
   resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
diff --git a/nomad/api/archive.py b/nomad/api/archive.py
index d8ed55af863e9d5e2fd5d80979d4d092ccaa86ef..75af737f66c41da3fe1e0a306d7b6c4b09614503 100644
--- a/nomad/api/archive.py
+++ b/nomad/api/archive.py
@@ -102,7 +102,7 @@ class ArchiveCalcResource(Resource):
 
 
 @ns.route('/metainfo/<string:metainfo_path>')
-@api.doc(params=dict(metainfo_path='A path or metainfo definition file name.'))
+@api.doc(params=dict(nomad_metainfo_path='A path or metainfo definition file name.'))
 class MetainfoResource(Resource):
     @api.doc('get_metainfo')
     @api.response(404, 'The metainfo does not exist')
@@ -113,13 +113,13 @@ class MetainfoResource(Resource):
         """
         try:
             file_dir = os.path.dirname(os.path.abspath(nomad_meta_info.__file__))
-            meta_info_path = os.path.normpath(os.path.join(file_dir, metainfo_path.strip()))
+            metainfo_file = os.path.normpath(os.path.join(file_dir, metainfo_path.strip()))
 
             rv = send_file(
-                meta_info_path,
+                metainfo_file,
                 mimetype='application/json',
                 as_attachment=True,
-                attachment_filename=os.path.basename(metainfo_path))
+                attachment_filename=os.path.basename(metainfo_file))
 
             return rv
         except FileNotFoundError:
diff --git a/nomad/api/upload.py b/nomad/api/upload.py
index 15861751f7e6efa83c214a9d076345bad6d8f0b1..3ae085d06dceb16659c0c70daf78da8d8aa44d54 100644
--- a/nomad/api/upload.py
+++ b/nomad/api/upload.py
@@ -41,7 +41,7 @@ ns = api.namespace(
 proc_model = api.model('Processing', {
     'tasks': fields.List(fields.String),
     'current_task': fields.String,
-    'tasks_completed': fields.Boolean,
+    'tasks_running': fields.Boolean,
     'tasks_status': fields.String,
     'errors': fields.List(fields.String),
     'warnings': fields.List(fields.String),
@@ -297,7 +297,7 @@ class UploadResource(Resource):
         if upload.user_id != str(g.user.user_id) and not g.user.is_admin:
             abort(401, message='Upload with id %s does not belong to you.' % upload_id)
 
-        if not upload.tasks_completed:
+        if upload.tasks_running:
             abort(400, message='The upload is not processed yet')
 
         try:
@@ -350,7 +350,7 @@ class UploadResource(Resource):
                 break
 
         if operation == 'commit':
-            if not upload.tasks_completed:
+            if upload.tasks_running:
                 abort(400, message='The upload is not processed yet')
             try:
                 upload.metadata = metadata
diff --git a/nomad/client.py b/nomad/client.py
index 5dce848741ca6188e0be4cde045beb1c62f6dee7..f8c29d0c6f423b98f1d434a4dc36d04771066f2a 100644
--- a/nomad/client.py
+++ b/nomad/client.py
@@ -327,12 +327,13 @@ def worker():
 
 
 @run.command(help='Run the nomad development api.')
-def api():
+@click.option('--debug', help='Does run flask in debug.', is_flag=True)
+def api(debug: bool):
     config.service = 'nomad_api'
     from nomad import infrastructure
     from nomad.api.__main__ import run_dev_server
     infrastructure.setup()
-    run_dev_server(debug=True, port=8000)
+    run_dev_server(debug=debug, port=8000)
 
 
 @cli.command(help='Runs tests and linting. Useful before commit code.')
diff --git a/nomad/processing/base.py b/nomad/processing/base.py
index 311a695adca0974dce4eed4e11e0acc5ab79c511..21b4f109755e832f0796564e0c5ad5761fb3725f 100644
--- a/nomad/processing/base.py
+++ b/nomad/processing/base.py
@@ -53,7 +53,7 @@ RUNNING = 'RUNNING'
 FAILURE = 'FAILURE'
 SUCCESS = 'SUCCESS'
 
-PROCESS_CALLED = 'CALLD'
+PROCESS_CALLED = 'CALLED'
 PROCESS_RUNNING = 'RUNNING'
 PROCESS_COMPLETED = 'COMPLETED'
 
@@ -130,9 +130,9 @@ class Proc(Document, metaclass=ProcMetaclass):
     process_status = StringField(default=None)
 
     @property
-    def tasks_completed(self) -> bool:
+    def tasks_running(self) -> bool:
         """ Returns True of the process has failed or succeeded. """
-        return self.tasks_status in [SUCCESS, FAILURE]
+        return self.tasks_status not in [SUCCESS, FAILURE]
 
     @property
     def process_running(self) -> bool:
@@ -194,7 +194,7 @@ class Proc(Document, metaclass=ProcMetaclass):
 
     def fail(self, *errors, log_level=logging.ERROR, **kwargs):
         """ Allows to fail the process. Takes strings or exceptions as args. """
-        assert not self.tasks_completed, 'Cannot fail a completed process.'
+        assert self.tasks_running, 'Cannot fail a completed process.'
 
         failed_with_exception = False
 
@@ -219,7 +219,7 @@ class Proc(Document, metaclass=ProcMetaclass):
 
     def warning(self, *warnings, log_level=logging.WARNING, **kwargs):
         """ Allows to save warnings. Takes strings or exceptions as args. """
-        assert not self.tasks_completed
+        assert self.tasks_running
 
         logger = self.get_logger(**kwargs)
 
@@ -266,7 +266,7 @@ class Proc(Document, metaclass=ProcMetaclass):
         Reloads the process constantly until it sees a completed process. Should be
         used with care as it can block indefinitely. Just intended for testing purposes.
         """
-        while not self.tasks_completed:
+        while self.tasks_running:
             time.sleep(interval)
             self.reload()
 
@@ -397,7 +397,7 @@ def task(func):
         except Exception as e:
             self.fail(e)
 
-        if self.__class__.tasks[-1] == self.current_task and not self.tasks_completed:
+        if self.__class__.tasks[-1] == self.current_task and self.tasks_running:
             self._complete()
 
     setattr(wrapper, '__task_name', func.__name__)
diff --git a/nomad/processing/data.py b/nomad/processing/data.py
index 98f7b651944df094e38bbabffad8ba40f82d0218..a3c2998fce58fcfa61fcebc8e7e992ac24ec7b0d 100644
--- a/nomad/processing/data.py
+++ b/nomad/processing/data.py
@@ -346,6 +346,8 @@ class Upload(Chord, datamodel.Upload):
             with utils.timer(
                     logger, 'staged upload deleted', step='delete',
                     upload_size=self.upload_files.size):
+                import time
+                time.sleep(10)
                 self.upload_files.delete()
                 self.delete()
 
diff --git a/tests/processing/test_data.py b/tests/processing/test_data.py
index 224b3363241ebf515762a24927d752e62b06637b..85c4fcecdc5461b56cd40593f0043a1b7b474f2f 100644
--- a/tests/processing/test_data.py
+++ b/tests/processing/test_data.py
@@ -82,7 +82,7 @@ def processed_upload(uploaded_id, test_user, worker, no_warn) -> Upload:
 
 
 def assert_processing(upload: Upload):
-    assert upload.tasks_completed
+    assert not upload.tasks_running
     assert upload.current_task == 'cleanup'
     assert upload.upload_id is not None
     assert len(upload.errors) == 0
@@ -127,7 +127,7 @@ def test_processing_with_warning(uploaded_id_with_warning, worker, test_user):
 def test_process_non_existing(worker, test_user, with_error):
     upload = run_processing('__does_not_exist', test_user)
 
-    assert upload.tasks_completed
+    assert not upload.tasks_running
     assert upload.current_task == 'extracting'
     assert upload.tasks_status == 'FAILURE'
     assert len(upload.errors) > 0
@@ -154,7 +154,7 @@ def test_task_failure(monkeypatch, uploaded_id, worker, task, test_user, with_er
     # run the test
     upload = run_processing(uploaded_id, test_user)
 
-    assert upload.tasks_completed
+    assert not upload.tasks_running
 
     if task != 'parsing':
         assert upload.tasks_status == 'FAILURE'
diff --git a/tests/test_api.py b/tests/test_api.py
index 80ccb0508bac58ca90c70ab700e1908a52470f59..e81fde6de2fefce2bc86efc7b5d2cc62f43d8e83 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -188,7 +188,7 @@ class TestUploads:
             assert rv.status_code == 200
             upload = self.assert_upload(rv.data)
             assert 'upload_time' in upload
-            if upload['tasks_completed']:
+            if not upload['tasks_running']:
                 break
 
         assert len(upload['tasks']) == 4