Propagate exceptions in sequence::size() (#2076)
diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h
index 4003d69..63cbf2e 100644
--- a/include/pybind11/pytypes.h
+++ b/include/pybind11/pytypes.h
@@ -1242,7 +1242,12 @@
 class sequence : public object {
 public:
     PYBIND11_OBJECT_DEFAULT(sequence, object, PySequence_Check)
-    size_t size() const { return (size_t) PySequence_Size(m_ptr); }
+    size_t size() const {
+        ssize_t result = PySequence_Size(m_ptr);
+        if (result == -1)
+            throw error_already_set();
+        return (size_t) result;
+    }
     bool empty() const { return size() == 0; }
     detail::sequence_accessor operator[](size_t index) const { return {*this, index}; }
     detail::item_accessor operator[](handle h) const { return object::operator[](h); }
diff --git a/tests/test_sequences_and_iterators.cpp b/tests/test_sequences_and_iterators.cpp
index 87ccf99..05f999b 100644
--- a/tests/test_sequences_and_iterators.cpp
+++ b/tests/test_sequences_and_iterators.cpp
@@ -319,6 +319,9 @@
         return l;
     });
 
+    // test_sequence_length: check that Python sequences can be converted to py::sequence.
+    m.def("sequence_length", [](py::sequence seq) { return seq.size(); });
+
     // Make sure that py::iterator works with std algorithms
     m.def("count_none", [](py::object o) {
         return std::count_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
diff --git a/tests/test_sequences_and_iterators.py b/tests/test_sequences_and_iterators.py
index 6bd1606..d839dbe 100644
--- a/tests/test_sequences_and_iterators.py
+++ b/tests/test_sequences_and_iterators.py
@@ -100,6 +100,25 @@
     assert cstats.move_assignments == 0
 
 
+def test_sequence_length():
+    """#2076: Exception raised by len(arg) should be propagated """
+    class BadLen(RuntimeError):
+        pass
+
+    class SequenceLike():
+        def __getitem__(self, i):
+            return None
+
+        def __len__(self):
+            raise BadLen()
+
+    with pytest.raises(BadLen):
+        m.sequence_length(SequenceLike())
+
+    assert m.sequence_length([1, 2, 3]) == 3
+    assert m.sequence_length("hello") == 5
+
+
 def test_map_iterator():
     sm = m.StringMap({'hi': 'bye', 'black': 'white'})
     assert sm['hi'] == 'bye'