Repository: conda/conda

Issue:
OSError: [Errno 28] No space left on device
```
error: OSError(28, 'No space left on device')
command: /home/ddbrothe/anaconda3/envs/tensorflow/bin/conda install keras
user_agent: conda/4.4.7 requests/2.14.2 CPython/3.6.1 Linux/4.10.0-35-generic ubuntu/16.04 glibc/2.23
_messageid: -9223372036837225447
_messagetime: 1515550319497 / 2018-01-09 20:11:59

Traceback (most recent call last):
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 270, in _make_single_record
    repodata_record = read_repodata_json(extracted_package_dir)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/gateways/disk/read.py", line 123, in read_repodata_json
    with open(join(extracted_package_directory, 'info', 'repodata_record.json')) as fi:
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/common/compat.py", line 120, in open
    closefd=closefd)
FileNotFoundError: [Errno 2] No such file or directory: '/home/ddbrothe/anaconda3/pkgs/mkl-2018.0.1-h19d6760_4/info/repodata_record.json'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 287, in _make_single_record
    index_json_record = read_index_json(extracted_package_dir)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/gateways/disk/read.py", line 111, in read_index_json
    with open(join(extracted_package_directory, 'info', 'index.json')) as fi:
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/common/compat.py", line 120, in open
    closefd=closefd)
FileNotFoundError: [Errno 2] No such file or directory: '/home/ddbrothe/anaconda3/pkgs/mkl-2018.0.1-h19d6760_4/info/index.json'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/exceptions.py", line 743, in __call__
    return func(*args, **kwargs)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/cli/main.py", line 78, in _main
    exit_code = do_call(args, p)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/cli/conda_argparse.py", line 76, in do_call
    exit_code = getattr(module, func_name)(args, parser)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/cli/main_install.py", line 11, in execute
    install(args, parser, 'install')
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/cli/install.py", line 255, in install
    handle_txn(progressive_fetch_extract, unlink_link_transaction, prefix, args, newenv)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/cli/install.py", line 272, in handle_txn
    unlink_link_transaction.display_actions(progressive_fetch_extract)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/link.py", line 706, in display_actions
    legacy_action_groups = self.make_legacy_action_groups(pfe)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/link.py", line 689, in make_legacy_action_groups
    pfe.prepare()
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/common/io.py", line 415, in decorated
    return f(*args, **kwds)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 540, in prepare
    for prec in self.link_precs)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 540, in <genexpr>
    for prec in self.link_precs)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 434, in make_actions_for_record
    ), None)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 431, in <genexpr>
    pcrec for pcrec in concat(PackageCache(pkgs_dir).query(pref_or_spec)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 432, in <genexpr>
    for pkgs_dir in context.pkgs_dirs)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 118, in query
    return (pcrec for pcrec in itervalues(self._package_cache_records) if pcrec == param)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 211, in _package_cache_records
    self.load()
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 90, in load
    package_cache_record = self._make_single_record(base_name)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/core/package_cache.py", line 308, in _make_single_record
    extract_tarball(package_tarball_full_path, extracted_package_dir)
  File "/home/ddbrothe/anaconda3/lib/python3.6/site-packages/conda/gateways/disk/create.py", line 145, in extract_tarball
    t.extractall(path=destination_directory, members=members_with_progress())
  File "/home/ddbrothe/anaconda3/lib/python3.6/tarfile.py", line 2007, in extractall
    numeric_owner=numeric_owner)
  File "/home/ddbrothe/anaconda3/lib/python3.6/tarfile.py", line 2049, in extract
    numeric_owner=numeric_owner)
  File "/home/ddbrothe/anaconda3/lib/python3.6/tarfile.py", line 2119, in _extract_member
    self.makefile(tarinfo, targetpath)
  File "/home/ddbrothe/anaconda3/lib/python3.6/tarfile.py", line 2168, in makefile
    copyfileobj(source, target, tarinfo.size, ReadError, bufsize)
  File "/home/ddbrothe/anaconda3/lib/python3.6/tarfile.py", line 251, in copyfileobj
    dst.write(buf)
OSError: [Errno 28] No space left on device
```


Discussion:

Resolving patch:
diff --git a/conda/exceptions.py b/conda/exceptions.py
--- a/conda/exceptions.py
+++ b/conda/exceptions.py
@@ -2,6 +2,7 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 from datetime import timedelta
+from errno import ENOSPC
 import json
 from logging import getLogger
 import os
@@ -675,6 +676,13 @@ def __init__(self, caused_by, **kwargs):
         super(EncodingError, self).__init__(message, caused_by=caused_by, **kwargs)
 
 
+class NoSpaceLeftError(CondaError):
+
+    def __init__(self, caused_by, **kwargs):
+        message = "No space left on devices."
+        super(NoSpaceLeftError, self).__init__(message, caused_by=caused_by, **kwargs)
+
+
 def maybe_raise(error, context):
     if isinstance(error, CondaMultiError):
         groups = groupby(lambda e: isinstance(e, ClobberError), error.errors)
@@ -769,17 +777,19 @@ def handle_exception(self, exc_val, exc_tb):
         return_code = getattr(exc_val, 'return_code', None)
         if return_code == 0:
             return 0
-        elif isinstance(exc_val, CondaError):
+        if isinstance(exc_val, CondaError):
             return self.handle_application_exception(exc_val, exc_tb)
-        elif isinstance(exc_val, UnicodeError) and PY2:
+        if isinstance(exc_val, UnicodeError) and PY2:
             return self.handle_application_exception(EncodingError(exc_val), exc_tb)
-        elif isinstance(exc_val, KeyboardInterrupt):
+        if isinstance(exc_val, EnvironmentError):
+            if getattr(exc_val, 'errno', None) == ENOSPC:
+                return self.handle_application_exception(NoSpaceLeftError(exc_val), exc_tb)
+        if isinstance(exc_val, KeyboardInterrupt):
             self._print_conda_exception(CondaError("KeyboardInterrupt"), _format_exc())
             return 1
-        elif isinstance(exc_val, SystemExit):
+        if isinstance(exc_val, SystemExit):
             return exc_val.code
-        else:
-            return self.handle_unexpected_exception(exc_val, exc_tb)
+        return self.handle_unexpected_exception(exc_val, exc_tb)
 
     def handle_application_exception(self, exc_val, exc_tb):
         self._print_conda_exception(exc_val, exc_tb)


Test patch: