Repository: readthedocs/readthedocs.org

Issue:
TypeError: sequence item 7: expected str instance, NoneType found
Sentry Issue: [READTHEDOCS-ORG-EMX](https://sentry.io/read-the-docs/readthedocs-org/issues/864447516/?referrer=github_integration)

```
TypeError: sequence item 7: expected str instance, NoneType found
(34 additional frame(s) were not displayed)
...
  File "readthedocs/doc_builder/environments.py", line 550, in __exit__
    ret = self.handle_exception(exc_type, exc_value, tb)
  File "readthedocs/doc_builder/environments.py", line 891, in __exit__
    return super().__exit__(exc_type, exc_value, tb)
  File "readthedocs/projects/tasks.py", line 568, in run_build
    log.warning('No build ID, not syncing files')
  File "readthedocs/projects/tasks.py", line 404, in run
    self.run_build(docker=docker, record=record)
  File "readthedocs/projects/tasks.py", line 281, in update_docs_task
    return step.run(project_id, *args, **kwargs)

(Build) [delira:tf_update_docs] sequence item 7: expected str instance, NoneType found
```


Discussion:

Resolving patch:
diff --git a/readthedocs/config/config.py b/readthedocs/config/config.py
--- a/readthedocs/config/config.py
+++ b/readthedocs/config/config.py
@@ -489,15 +489,14 @@ def validate_conda(self):
             raw_conda = self.raw_config['conda']
             with self.catch_validation_error('conda'):
                 validate_dict(raw_conda)
-            conda_environment = None
-            if 'file' in raw_conda:
-                with self.catch_validation_error('conda.file'):
-                    conda_environment = validate_file(
-                        raw_conda['file'],
-                        self.base_path,
-                    )
-            conda['environment'] = conda_environment
-
+            with self.catch_validation_error('conda.file'):
+                if 'file' not in raw_conda:
+                    raise ValidationError('file', VALUE_NOT_FOUND)
+                conda_environment = validate_file(
+                    raw_conda['file'],
+                    self.base_path,
+                )
+                conda['environment'] = conda_environment
             return conda
         return None
 


Test patch:
diff --git a/readthedocs/config/tests/test_config.py b/readthedocs/config/tests/test_config.py
--- a/readthedocs/config/tests/test_config.py
+++ b/readthedocs/config/tests/test_config.py
@@ -557,29 +557,33 @@ def test_it_priorities_image_from_env_config(self, tmpdir, image):
         assert build.build.image == image
 
 
-def test_use_conda_default_false():
+def test_use_conda_default_none():
     build = get_build_config({})
     build.validate()
     assert build.conda is None
 
 
-def test_use_conda_respects_config():
+def test_validates_conda_file(tmpdir):
+    apply_fs(tmpdir, {'environment.yml': ''})
     build = get_build_config(
-        {'conda': {}},
+        {'conda': {'file': 'environment.yml'}},
+        source_file=str(tmpdir.join('readthedocs.yml')),
     )
     build.validate()
     assert isinstance(build.conda, Conda)
+    assert build.conda.environment == str(tmpdir.join('environment.yml'))
 
 
-def test_validates_conda_file(tmpdir):
+def test_file_is_required_when_using_conda(tmpdir):
     apply_fs(tmpdir, {'environment.yml': ''})
     build = get_build_config(
-        {'conda': {'file': 'environment.yml'}},
+        {'conda': {'foo': 'environment.yml'}},
         source_file=str(tmpdir.join('readthedocs.yml')),
     )
-    build.validate()
-    assert isinstance(build.conda, Conda)
-    assert build.conda.environment == str(tmpdir.join('environment.yml'))
+    with raises(InvalidConfig) as excinfo:
+        build.validate()
+    assert excinfo.value.key == 'conda.file'
+    assert excinfo.value.code == VALUE_NOT_FOUND
 
 
 def test_requirements_file_empty():