diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c9d549..b732eb9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 ## 0.5.2
 
+### Changed
+
+* If there is more than one release, but the `date` field is missing or null, the `MissingDateKeyError` and `NullDateValueError` exceptions are raised, respestively, instead of the generic `KeyError` and `TypeError`.
+
 ### Fixed
 
 * If a field's value is set to `null`, it is omitted from the compiled release.
diff --git a/ocdsmerge/merge.py b/ocdsmerge/merge.py
index 7f6c1ef..842cb66 100644
--- a/ocdsmerge/merge.py
+++ b/ocdsmerge/merge.py
@@ -31,6 +31,18 @@ class IdDict(OrderedDict):
         self._identifier = identifier
 
 
+class OCDSMergeError(Exception):
+    """Base class for exceptions from within this package"""
+
+
+class MissingDateKeyError(OCDSMergeError):
+    """Raised when a release is missing a 'date' key"""
+
+
+class NullDateValueError(OCDSMergeError):
+    """Raised when a release has a null 'date' value"""
+
+
 @lru_cache()
 def get_tags():
     """
@@ -274,6 +286,20 @@ def process_flattened(flattened):
     return processed
 
 
+def sorted_releases(releases):
+    """
+    Sorts a list of releases by date.
+    """
+    if len(releases) == 1:
+        return releases
+    try:
+        return sorted(releases, key=lambda release: release['date'])
+    except KeyError:
+        raise MissingDateKeyError
+    except TypeError:
+        raise NullDateValueError
+
+
 def merge(releases, schema=None, merge_rules=None):
     """
     Merges a list of releases into a compiledRelease.
@@ -282,11 +308,12 @@ def merge(releases, schema=None, merge_rules=None):
         merge_rules = get_merge_rules(schema)
 
     merged = OrderedDict({('tag',): ['compiled']})
-    for release in sorted(releases, key=lambda release: release['date']):
+    for release in sorted_releases(releases):
         release = release.copy()
 
-        ocid = release['ocid']
-        date = release['date']
+        # `ocid` and `date` are required fields, but the data can be invalid.
+        ocid = release.get('ocid')
+        date = release.get('date')
         # Prior to OCDS 1.1.4, `tag` didn't set "omitWhenMerged": true.
         release.pop('tag', None)  # becomes ["compiled"]
 
@@ -313,15 +340,16 @@ def merge_versioned(releases, schema=None, merge_rules=None):
         merge_rules = get_merge_rules(schema)
 
     merged = OrderedDict()
-    for release in sorted(releases, key=lambda release: release['date']):
+    for release in sorted_releases(releases):
         release = release.copy()
 
         # Don't version the OCID.
-        ocid = release.pop('ocid')
+        ocid = release.pop('ocid', None)
         merged[('ocid',)] = ocid
 
-        releaseID = release['id']
-        date = release['date']
+        # `id` and `date` are required fields, but the data can be invalid.
+        releaseID = release.get('id')
+        date = release.get('date')
         # Prior to OCDS 1.1.4, `tag` didn't set "omitWhenMerged": true.
         tag = release.pop('tag', None)
 

diff --git a/tests/test_merge.py b/tests/test_merge.py
index 1b25c32..7b4df8e 100644
--- a/tests/test_merge.py
+++ b/tests/test_merge.py
@@ -24,7 +24,8 @@ from jsonschema import FormatChecker
 from jsonschema.validators import Draft4Validator as validator
 
 from ocdsmerge import merge, merge_versioned, get_merge_rules
-from ocdsmerge.merge import get_tags, get_release_schema_url, flatten, process_flattened
+from ocdsmerge.merge import (get_tags, get_release_schema_url, flatten, process_flattened, MissingDateKeyError,
+                             NullDateValueError)
 
 tags = {
     '1.0': '1__0__3',
@@ -64,6 +65,30 @@ def custom_warning_formatter(message, category, filename, lineno, line=None):
 warnings.formatwarning = custom_warning_formatter
 
 
+@pytest.mark.parametrize('error, data', [(MissingDateKeyError, {}), (NullDateValueError, {'date': None})])
+def test_date_errors(error, data):
+    for method in (merge, merge_versioned):
+        with pytest.raises(error):
+            method([{'date': '2010-01-01'}, data])
+
+    release = deepcopy(data)
+    assert merge([release]) == {
+        'id': 'None-None',
+        'tag': ['compiled'],
+    }
+
+    release = deepcopy(data)
+    release['initiationType'] = 'tender'
+    assert merge_versioned([release]) == {
+        'initiationType': [{
+            'releaseID': None,
+            'releaseDate': None,
+            'releaseTag': None,
+            'value': 'tender',
+        }],
+    }
+
+
 @pytest.mark.parametrize('filename,schema', test_merge_argvalues)
 def test_merge(filename, schema):
     if filename.endswith('-compiled.json'):

Crashs if no 'date' key in data.
https://github.com/open-contracting/ocds-merge/blob/master/ocdsmerge/merge.py#L316

We are currently seeing crashes in Kingfisher process where there is data with no 'date' key.

In fairness, I'm not sure what the merge library can actually do in this case 😄 ... but maybe we want to think about good ways to report this upwards.
tests/test_merge.py::test_date_errors[MissingDateKeyError-data0] tests/test_merge.py::test_date_errors[NullDateValueError-data1] tests/test_merge.py::test_merge[tests/fixtures/1.1/null-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-identifiermerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/simple-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-wholelistmerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-wholelistmerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-object-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/unit-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-object-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/lists-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-object-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/string-list-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-identifiermerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/mergeid-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/initial-null-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/contextual-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-identifiermerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-wholelistmerge-array-compiled.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-wholelistmerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-object-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-identifiermerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-object-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-wholelistmerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/mergeid-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/null-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-object-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/initial-null-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/unit-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-wholelistmerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/simple-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/contextual-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-identifiermerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/lists-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-identifiermerge-array-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/string-list-versioned.json-None] tests/test_merge.py::test_merge[tests/fixtures/1.1/null-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-identifiermerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/simple-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-wholelistmerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-wholelistmerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-object-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/unit-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-object-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/lists-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-object-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/string-list-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-identifiermerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/mergeid-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/initial-null-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/contextual-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-identifiermerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-wholelistmerge-array-compiled.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-wholelistmerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-object-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-identifiermerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-object-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-wholelistmerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/mergeid-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/null-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-object-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/initial-null-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/unit-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/empty-wholelistmerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/simple-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/contextual-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/fill-identifiermerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/lists-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/single-empty-identifiermerge-array-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.1/string-list-versioned.json-http://standard.open-contracting.org/schema/1__1__2/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.0/suppliers-compiled.json-http://standard.open-contracting.org/schema/1__0__3/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/1.0/suppliers-versioned.json-http://standard.open-contracting.org/schema/1__0__3/release-schema.json] tests/test_merge.py::test_merge[tests/fixtures/schema/omit-when-merged-array-of-non-objects-compiled.json-schema70] tests/test_merge.py::test_merge[tests/fixtures/schema/whole-list-merge-object-compiled.json-schema71] tests/test_merge.py::test_merge[tests/fixtures/schema/deep-identifier-merge-compiled.json-schema72] tests/test_merge.py::test_merge[tests/fixtures/schema/deep-whole-list-merge-compiled.json-schema73] tests/test_merge.py::test_merge[tests/fixtures/schema/omit-when-merged-shadowed-compiled.json-schema74] tests/test_merge.py::test_merge[tests/fixtures/schema/deep-omit-when-merged-compiled.json-schema75] tests/test_merge.py::test_merge[tests/fixtures/schema/whole-list-merge-duplicate-id-compiled.json-schema76] tests/test_merge.py::test_merge[tests/fixtures/schema/whole-list-merge-no-id-compiled.json-schema77] tests/test_merge.py::test_merge[tests/fixtures/schema/identifier-merge-duplicate-id-compiled.json-schema78] tests/test_merge.py::test_merge[tests/fixtures/schema/no-top-level-id-compiled.json-schema79] tests/test_merge.py::test_merge[tests/fixtures/schema/identifier-merge-collision-compiled.json-schema80] tests/test_merge.py::test_merge[tests/fixtures/schema/merge-property-is-false-compiled.json-schema81] tests/test_merge.py::test_merge[tests/fixtures/schema/whole-list-merge-empty-compiled.json-schema82] tests/test_merge.py::test_merge[tests/fixtures/schema/version-id-versioned.json-schema83] tests/test_merge.py::test_merge_when_array_is_mixed[0-0] tests/test_merge.py::test_merge_when_array_is_mixed[0-1] tests/test_merge.py::test_merge_when_array_is_mixed[1-0] tests/test_merge.py::test_merge_when_array_is_mixed[1-1] tests/test_merge.py::test_merge_when_array_is_mixed_without_schema[0-0] tests/test_merge.py::test_merge_when_array_is_mixed_without_schema[0-1] tests/test_merge.py::test_merge_when_array_is_mixed_without_schema[1-0] tests/test_merge.py::test_merge_when_array_is_mixed_without_schema[1-1] tests/test_merge.py::test_get_tags tests/test_merge.py::test_get_release_schema_url tests/test_merge.py::test_get_merge_rules_1_1 tests/test_merge.py::test_get_merge_rules_1_0 tests/test_merge.py::test_flatten tests/test_merge.py::test_process_flattened tests/test_merge.py::test_valid[tests/fixtures/1.0/suppliers-compiled.json-schema0] tests/test_merge.py::test_valid[tests/fixtures/1.0/suppliers.json-schema1] tests/test_merge.py::test_valid[tests/fixtures/1.0/suppliers-versioned.json-schema2] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-object.json-schema3] tests/test_merge.py::test_valid[tests/fixtures/1.1/null-compiled.json-schema4] tests/test_merge.py::test_valid[tests/fixtures/1.1/initial-null.json-schema5] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-wholelistmerge-array.json-schema7] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-identifiermerge-array.json-schema8] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-identifiermerge-array-compiled.json-schema9] tests/test_merge.py::test_valid[tests/fixtures/1.1/string-list.json-schema10] tests/test_merge.py::test_valid[tests/fixtures/1.1/simple-compiled.json-schema11] tests/test_merge.py::test_valid[tests/fixtures/1.1/mergeid.json-schema12] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-wholelistmerge-array-compiled.json-schema13] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-wholelistmerge-array.json-schema14] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-object.json-schema15] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-wholelistmerge-array-compiled.json-schema16] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-object-compiled.json-schema17] tests/test_merge.py::test_valid[tests/fixtures/1.1/unit-compiled.json-schema18] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-object.json-schema19] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-identifiermerge-array.json-schema20] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-object-compiled.json-schema21] tests/test_merge.py::test_valid[tests/fixtures/1.1/null.json-schema22] tests/test_merge.py::test_valid[tests/fixtures/1.1/lists-compiled.json-schema23] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-identifiermerge-array.json-schema24] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-object-compiled.json-schema25] tests/test_merge.py::test_valid[tests/fixtures/1.1/unit.json-schema26] tests/test_merge.py::test_valid[tests/fixtures/1.1/lists.json-schema27] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-wholelistmerge-array.json-schema28] tests/test_merge.py::test_valid[tests/fixtures/1.1/string-list-compiled.json-schema29] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-identifiermerge-array-compiled.json-schema30] tests/test_merge.py::test_valid[tests/fixtures/1.1/simple.json-schema31] tests/test_merge.py::test_valid[tests/fixtures/1.1/mergeid-compiled.json-schema32] tests/test_merge.py::test_valid[tests/fixtures/1.1/initial-null-compiled.json-schema33] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-identifiermerge-array-compiled.json-schema35] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-wholelistmerge-array-compiled.json-schema36] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-wholelistmerge-array-versioned.json-schema37] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-object-versioned.json-schema38] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-identifiermerge-array-versioned.json-schema39] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-object-versioned.json-schema40] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-wholelistmerge-array-versioned.json-schema41] tests/test_merge.py::test_valid[tests/fixtures/1.1/mergeid-versioned.json-schema42] tests/test_merge.py::test_valid[tests/fixtures/1.1/null-versioned.json-schema43] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-object-versioned.json-schema44] tests/test_merge.py::test_valid[tests/fixtures/1.1/initial-null-versioned.json-schema45] tests/test_merge.py::test_valid[tests/fixtures/1.1/unit-versioned.json-schema46] tests/test_merge.py::test_valid[tests/fixtures/1.1/empty-wholelistmerge-array-versioned.json-schema47] tests/test_merge.py::test_valid[tests/fixtures/1.1/simple-versioned.json-schema48] tests/test_merge.py::test_valid[tests/fixtures/1.1/fill-identifiermerge-array-versioned.json-schema50] tests/test_merge.py::test_valid[tests/fixtures/1.1/lists-versioned.json-schema51] tests/test_merge.py::test_valid[tests/fixtures/1.1/single-empty-identifiermerge-array-versioned.json-schema52] tests/test_merge.py::test_valid[tests/fixtures/1.1/string-list-versioned.json-schema53]