diff --git a/adl/rot13adl/rot13node.go b/adl/rot13adl/rot13node.go
index 619dd748..9049c1fe 100644
--- a/adl/rot13adl/rot13node.go
+++ b/adl/rot13adl/rot13node.go
@@ -58,8 +58,8 @@ func (*_R13String) MapIterator() datamodel.MapIterator {
 func (*_R13String) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (*_R13String) Length() int64 {
-	return -1
+func (*_R13String) Length() (int64, error) {
+	return -1, nil
 }
 func (*_R13String) IsAbsent() bool {
 	return false
diff --git a/adl/rot13adl/rot13substrate.go b/adl/rot13adl/rot13substrate.go
index 511475ad..618e2056 100644
--- a/adl/rot13adl/rot13substrate.go
+++ b/adl/rot13adl/rot13substrate.go
@@ -51,8 +51,8 @@ func (*_Substrate) MapIterator() datamodel.MapIterator {
 func (*_Substrate) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (*_Substrate) Length() int64 {
-	return -1
+func (*_Substrate) Length() (int64, error) {
+	return -1, nil
 }
 func (*_Substrate) IsAbsent() bool {
 	return false
diff --git a/codec/dagcbor/marshal.go b/codec/dagcbor/marshal.go
index a7ee1620..790cedeb 100644
--- a/codec/dagcbor/marshal.go
+++ b/codec/dagcbor/marshal.go
@@ -70,7 +70,10 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
 	case datamodel.Kind_List:
 		// Emit start of list.
 		tk.Type = tok.TArrOpen
-		l := n.Length()
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
 		tk.Length = int(l) // TODO: overflow check
 		if _, err := sink.Step(tk); err != nil {
 			return err
@@ -87,7 +90,7 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
 		}
 		// Emit list close.
 		tk.Type = tok.TArrClose
-		_, err := sink.Step(tk)
+		_, err = sink.Step(tk)
 		return err
 	case datamodel.Kind_Bool:
 		v, err := n.AsBool()
@@ -174,8 +177,11 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
 func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options EncodeOptions) error {
 	// Emit start of map.
 	tk.Type = tok.TMapOpen
-	expectedLength := int(n.Length())
-	tk.Length = expectedLength // TODO: overflow check
+	expectedLength, err := n.Length()
+	if err != nil {
+		return err
+	}
+	tk.Length = int(expectedLength) // TODO: overflow check
 	if _, err := sink.Step(tk); err != nil {
 		return err
 	}
@@ -197,7 +203,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
 			}
 			entries = append(entries, entry{keyStr, v})
 		}
-		if len(entries) != expectedLength {
+		if len(entries) != int(expectedLength) {
 			return fmt.Errorf("map Length() does not match number of MapIterator() entries")
 		}
 		// Apply the desired sort function.
@@ -229,7 +235,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
 		}
 	} else { // no sorting
 		// Emit map contents (and recurse).
-		var entryCount int
+		var entryCount int64
 		for itr := n.MapIterator(); !itr.Done(); {
 			k, v, err := itr.Next()
 			if err != nil {
@@ -254,7 +260,7 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
 	}
 	// Emit map close.
 	tk.Type = tok.TMapClose
-	_, err := sink.Step(tk)
+	_, err = sink.Step(tk)
 	return err
 }
 
@@ -272,7 +278,11 @@ func EncodedLength(n datamodel.Node) (int64, error) {
 	case datamodel.Kind_Null:
 		return 1, nil // 0xf6
 	case datamodel.Kind_Map:
-		length := uintLength(uint64(n.Length())) // length prefixed major 5
+		l, err := n.Length()
+		if err != nil {
+			return 0, err
+		}
+		length := uintLength(uint64(l)) // length prefixed major 5
 		for itr := n.MapIterator(); !itr.Done(); {
 			k, v, err := itr.Next()
 			if err != nil {
@@ -291,7 +301,10 @@ func EncodedLength(n datamodel.Node) (int64, error) {
 		}
 		return length, nil
 	case datamodel.Kind_List:
-		nl := n.Length()
+		nl, err := n.Length()
+		if err != nil {
+			return 0, err
+		}
 		length := uintLength(uint64(nl)) // length prefixed major 4
 		for i := int64(0); i < nl; i++ {
 			v, err := n.LookupByIndex(i)
diff --git a/codec/dagjson/marshal.go b/codec/dagjson/marshal.go
index 2fe39680..33e20ee2 100644
--- a/codec/dagjson/marshal.go
+++ b/codec/dagjson/marshal.go
@@ -61,8 +61,11 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
 	case datamodel.Kind_Map:
 		// Emit start of map.
 		tk.Type = tok.TMapOpen
-		expectedLength := int(n.Length())
-		tk.Length = expectedLength // TODO: overflow check
+		expectedLength, err := n.Length()
+		if err != nil {
+			return err
+		}
+		tk.Length = int(expectedLength) // TODO: overflow check
 		if _, err := sink.Step(&tk); err != nil {
 			return err
 		}
@@ -84,7 +87,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
 				}
 				entries = append(entries, entry{keyStr, v})
 			}
-			if len(entries) != expectedLength {
+			if len(entries) != int(expectedLength) {
 				return fmt.Errorf("map Length() does not match number of MapIterator() entries")
 			}
 			// Apply the desired sort function.
@@ -104,7 +107,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
 				})
 			}
 			// Emit map contents (and recurse).
-			var entryCount int
+			var entryCount int64
 			for _, e := range entries {
 				tk.Type = tok.TString
 				tk.Str = e.key
@@ -141,12 +144,15 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
 		}
 		// Emit map close.
 		tk.Type = tok.TMapClose
-		_, err := sink.Step(&tk)
+		_, err = sink.Step(&tk)
 		return err
 	case datamodel.Kind_List:
 		// Emit start of list.
 		tk.Type = tok.TArrOpen
-		l := n.Length()
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
 		tk.Length = int(l) // TODO: overflow check
 		if _, err := sink.Step(&tk); err != nil {
 			return err
@@ -163,7 +169,7 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
 		}
 		// Emit list close.
 		tk.Type = tok.TArrClose
-		_, err := sink.Step(&tk)
+		_, err = sink.Step(&tk)
 		return err
 	case datamodel.Kind_Bool:
 		v, err := n.AsBool()
diff --git a/codecHelpers_test.go b/codecHelpers_test.go
index a515f0c4..23f0deb3 100644
--- a/codecHelpers_test.go
+++ b/codecHelpers_test.go
@@ -49,7 +49,8 @@ func Example_unmarshal_withSchema() {
 	n, err := ipld.Unmarshal(serial, json.Decode, &foobar, typesys.TypeByName("Foobar"))
 	fmt.Printf("error: %v\n", err)
 	fmt.Printf("go struct: %v\n", foobar)
-	fmt.Printf("node kind and length: %s, %d\n", n.Kind(), n.Length())
+	l, _ := n.Length()
+	fmt.Printf("node kind and length: %s, %d\n", n.Kind(), l)
 	fmt.Printf("node lookup 'foo': %q\n", must.String(must.Node(n.LookupByString("foo"))))
 
 	// Output:
diff --git a/datamodel/copy.go b/datamodel/copy.go
index cedfb53e..f12ace77 100644
--- a/datamodel/copy.go
+++ b/datamodel/copy.go
@@ -67,7 +67,11 @@ func Copy(n Node, na NodeAssembler) error {
 		}
 		return na.AssignLink(v)
 	case Kind_Map:
-		ma, err := na.BeginMap(n.Length())
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
+		ma, err := na.BeginMap(l)
 		if err != nil {
 			return err
 		}
@@ -89,7 +93,11 @@ func Copy(n Node, na NodeAssembler) error {
 		}
 		return ma.Finish()
 	case Kind_List:
-		la, err := na.BeginList(n.Length())
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
+		la, err := na.BeginList(l)
 		if err != nil {
 			return err
 		}
diff --git a/datamodel/equal.go b/datamodel/equal.go
index 8c476113..e3bc6bae 100644
--- a/datamodel/equal.go
+++ b/datamodel/equal.go
@@ -106,7 +106,15 @@ func DeepEqual(x, y Node) bool {
 
 	// Recursive kinds.
 	case Kind_Map:
-		if x.Length() != y.Length() {
+		xl, err := x.Length()
+		if err != nil {
+			panic(err)
+		}
+		yl, err := y.Length()
+		if err != nil {
+			panic(err)
+		}
+		if xl != yl {
 			return false
 		}
 		xitr := x.MapIterator()
@@ -129,7 +137,15 @@ func DeepEqual(x, y Node) bool {
 		}
 		return true
 	case Kind_List:
-		if x.Length() != y.Length() {
+		xl, err := x.Length()
+		if err != nil {
+			panic(err)
+		}
+		yl, err := y.Length()
+		if err != nil {
+			panic(err)
+		}
+		if xl != yl {
 			return false
 		}
 		xitr := x.ListIterator()
diff --git a/datamodel/node.go b/datamodel/node.go
index 625f472d..db993bfe 100644
--- a/datamodel/node.go
+++ b/datamodel/node.go
@@ -130,7 +130,7 @@ type Node interface {
 
 	// Length returns the length of a list, or the number of entries in a map,
 	// or -1 if the node is not of list nor map kind.
-	Length() int64
+	Length() (int64, error)
 
 	// Absent nodes are returned when traversing a struct field that is
 	// defined by a schema but unset in the data.  (Absent nodes are not
diff --git a/datamodel/unit.go b/datamodel/unit.go
index afc2e3e1..d6f955fa 100644
--- a/datamodel/unit.go
+++ b/datamodel/unit.go
@@ -31,8 +31,8 @@ func (nullNode) MapIterator() MapIterator {
 func (nullNode) ListIterator() ListIterator {
 	return nil
 }
-func (nullNode) Length() int64 {
-	return -1
+func (nullNode) Length() (int64, error) {
+	return -1, nil
 }
 func (nullNode) IsAbsent() bool {
 	return false
@@ -110,8 +110,8 @@ func (absentNode) MapIterator() MapIterator {
 func (absentNode) ListIterator() ListIterator {
 	return nil
 }
-func (absentNode) Length() int64 {
-	return -1
+func (absentNode) Length() (int64, error) {
+	return -1, nil
 }
 func (absentNode) IsAbsent() bool {
 	return true
diff --git a/examples_test.go b/examples_test.go
index ed78b02f..deb08329 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -48,7 +48,8 @@ func Example_unmarshalData() {
 	n := nb.Build()               // Call 'Build' to get the resulting Node.  (It's immutable!)
 
 	fmt.Printf("the data decoded was a %s kind\n", n.Kind())
-	fmt.Printf("the length of the node is %d\n", n.Length())
+	l, _ := n.Length()
+	fmt.Printf("the length of the node is %d\n", l)
 
 	// Output:
 	// the data decoded was a map kind
diff --git a/fluent/fluentBuilder_test.go b/fluent/fluentBuilder_test.go
index 81d5ea61..1f9f49e5 100644
--- a/fluent/fluentBuilder_test.go
+++ b/fluent/fluentBuilder_test.go
@@ -34,11 +34,15 @@ func TestBuild(t *testing.T) {
 			})
 		})
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-		qt.Check(t, n.Length(), qt.Equals, int64(3))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(3))
 		qt.Check(t, must.String(must.Node(n.LookupByString("k1"))), qt.Equals, "fine")
 		qt.Check(t, must.String(must.Node(n.LookupByString("k2"))), qt.Equals, "super")
 		n = must.Node(n.LookupByString("k3"))
-		qt.Check(t, n.Length(), qt.Equals, int64(3))
+		l, err = n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(3))
 		qt.Check(t, must.String(must.Node(n.LookupByString("k31"))), qt.Equals, "thanks")
 		qt.Check(t, must.String(must.Node(n.LookupByString("k32"))), qt.Equals, "for")
 		qt.Check(t, must.String(must.Node(n.LookupByString("k33"))), qt.Equals, "asking")
@@ -56,16 +60,24 @@ func TestBuild(t *testing.T) {
 			})
 		})
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-		qt.Check(t, n.Length(), qt.Equals, int64(1))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(1))
 		n = must.Node(n.LookupByIndex(0))
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-		qt.Check(t, n.Length(), qt.Equals, int64(1))
+		l, err = n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(1))
 		n = must.Node(n.LookupByIndex(0))
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-		qt.Check(t, n.Length(), qt.Equals, int64(1))
+		l, err = n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(1))
 		n = must.Node(n.LookupByIndex(0))
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-		qt.Check(t, n.Length(), qt.Equals, int64(1))
+		l, err = n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(1))
 		n = must.Node(n.LookupByIndex(0))
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Int)
 		qt.Check(t, must.Int(n), qt.Equals, int64(2))
diff --git a/fluent/reflect_test.go b/fluent/reflect_test.go
index 83744d35..8d7cd59a 100644
--- a/fluent/reflect_test.go
+++ b/fluent/reflect_test.go
@@ -25,11 +25,15 @@ func TestReflect(t *testing.T) {
 		qt.Check(t, err, qt.IsNil)
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
 		t.Run("CorrectContents", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			qt.Check(t, must.String(must.Node(n.LookupByString("k1"))), qt.Equals, "fine")
 			qt.Check(t, must.String(must.Node(n.LookupByString("k2"))), qt.Equals, "super")
 			n := must.Node(n.LookupByString("k3"))
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err = n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			qt.Check(t, must.String(must.Node(n.LookupByString("k31"))), qt.Equals, "thanks")
 			qt.Check(t, must.String(must.Node(n.LookupByString("k32"))), qt.Equals, "for")
 			qt.Check(t, must.String(must.Node(n.LookupByString("k33"))), qt.Equals, "asking")
@@ -69,11 +73,15 @@ func TestReflect(t *testing.T) {
 		qt.Check(t, err, qt.IsNil)
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
 		t.Run("CorrectContents", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			qt.Check(t, must.String(must.Node(n.LookupByString("X"))), qt.Equals, "fine")
 			qt.Check(t, must.String(must.Node(n.LookupByString("Z"))), qt.Equals, "super")
 			n := must.Node(n.LookupByString("M"))
-			qt.Check(t, n.Length(), qt.Equals, int64(2))
+			l, err = n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(2))
 			qt.Check(t, must.String(must.Node(n.LookupByString("A"))), qt.Equals, "thanks")
 			qt.Check(t, must.String(must.Node(n.LookupByString("B"))), qt.Equals, "really")
 		})
diff --git a/fluent/toInterfaceValue.go b/fluent/toInterfaceValue.go
index b9ed8beb..e72e7939 100644
--- a/fluent/toInterfaceValue.go
+++ b/fluent/toInterfaceValue.go
@@ -34,7 +34,11 @@ func ToInterface(node datamodel.Node) (interface{}, error) {
 	case datamodel.Kind_Link:
 		return node.AsLink()
 	case datamodel.Kind_Map:
-		outMap := make(map[string]interface{}, node.Length())
+		l, err := node.Length()
+		if err != nil {
+			return nil, err
+		}
+		outMap := make(map[string]interface{}, l)
 		for mi := node.MapIterator(); !mi.Done(); {
 			k, v, err := mi.Next()
 			if err != nil {
@@ -52,7 +56,11 @@ func ToInterface(node datamodel.Node) (interface{}, error) {
 		}
 		return outMap, nil
 	case datamodel.Kind_List:
-		outList := make([]interface{}, 0, node.Length())
+		l, err := node.Length()
+		if err != nil {
+			return nil, err
+		}
+		outList := make([]interface{}, 0, l)
 		for li := node.ListIterator(); !li.Done(); {
 			_, v, err := li.Next()
 			if err != nil {
diff --git a/linking/linkingExamples_test.go b/linking/linkingExamples_test.go
index 73984737..ef70bad2 100644
--- a/linking/linkingExamples_test.go
+++ b/linking/linkingExamples_test.go
@@ -126,7 +126,8 @@ func ExampleLinkSystem_Load() {
 	}
 
 	// Tada!  We have the data as node that we can traverse and use as desired.
-	fmt.Printf("we loaded a %s with %d entries\n", n.Kind(), n.Length())
+	l, _ := n.Length()
+	fmt.Printf("we loaded a %s with %d entries\n", n.Kind(), l)
 
 	// Output:
 	// we loaded a map with 1 entries
diff --git a/node/basicnode/bool.go b/node/basicnode/bool.go
index ecf85fad..b836a756 100644
--- a/node/basicnode/bool.go
+++ b/node/basicnode/bool.go
@@ -43,8 +43,8 @@ func (plainBool) MapIterator() datamodel.MapIterator {
 func (plainBool) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainBool) Length() int64 {
-	return -1
+func (plainBool) Length() (int64, error) {
+	return -1, nil
 }
 func (plainBool) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/bytes.go b/node/basicnode/bytes.go
index 566c32fe..e10f0119 100644
--- a/node/basicnode/bytes.go
+++ b/node/basicnode/bytes.go
@@ -46,8 +46,8 @@ func (plainBytes) MapIterator() datamodel.MapIterator {
 func (plainBytes) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainBytes) Length() int64 {
-	return -1
+func (plainBytes) Length() (int64, error) {
+	return -1, nil
 }
 func (plainBytes) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/bytes_stream.go b/node/basicnode/bytes_stream.go
index ad238bcf..7ef24e99 100644
--- a/node/basicnode/bytes_stream.go
+++ b/node/basicnode/bytes_stream.go
@@ -46,8 +46,8 @@ func (streamBytes) MapIterator() datamodel.MapIterator {
 func (streamBytes) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (streamBytes) Length() int64 {
-	return -1
+func (streamBytes) Length() (int64, error) {
+	return -1, nil
 }
 func (streamBytes) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/float.go b/node/basicnode/float.go
index f00db30d..87e3af76 100644
--- a/node/basicnode/float.go
+++ b/node/basicnode/float.go
@@ -43,8 +43,8 @@ func (plainFloat) MapIterator() datamodel.MapIterator {
 func (plainFloat) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainFloat) Length() int64 {
-	return -1
+func (plainFloat) Length() (int64, error) {
+	return -1, nil
 }
 func (plainFloat) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/int.go b/node/basicnode/int.go
index d8e8ac2f..7db3785d 100644
--- a/node/basicnode/int.go
+++ b/node/basicnode/int.go
@@ -58,8 +58,8 @@ func (plainInt) MapIterator() datamodel.MapIterator {
 func (plainInt) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainInt) Length() int64 {
-	return -1
+func (plainInt) Length() (int64, error) {
+	return -1, nil
 }
 func (plainInt) IsAbsent() bool {
 	return false
@@ -117,8 +117,8 @@ func (plainUint) MapIterator() datamodel.MapIterator {
 func (plainUint) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainUint) Length() int64 {
-	return -1
+func (plainUint) Length() (int64, error) {
+	return -1, nil
 }
 func (plainUint) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/link.go b/node/basicnode/link.go
index 41d2cf0d..c377e585 100644
--- a/node/basicnode/link.go
+++ b/node/basicnode/link.go
@@ -44,8 +44,8 @@ func (plainLink) MapIterator() datamodel.MapIterator {
 func (plainLink) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainLink) Length() int64 {
-	return -1
+func (plainLink) Length() (int64, error) {
+	return -1, nil
 }
 func (plainLink) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/list.go b/node/basicnode/list.go
index 6f7582bb..a4b7b82c 100644
--- a/node/basicnode/list.go
+++ b/node/basicnode/list.go
@@ -31,7 +31,11 @@ func (plainList) LookupByNode(datamodel.Node) (datamodel.Node, error) {
 	return mixins.List{TypeName: "list"}.LookupByNode(nil)
 }
 func (n *plainList) LookupByIndex(idx int64) (datamodel.Node, error) {
-	if n.Length() <= idx {
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
+	if l <= idx {
 		return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
 	}
 	return n.x[idx], nil
@@ -49,8 +53,8 @@ func (plainList) MapIterator() datamodel.MapIterator {
 func (n *plainList) ListIterator() datamodel.ListIterator {
 	return &plainList_ListIterator{n, 0}
 }
-func (n *plainList) Length() int64 {
-	return int64(len(n.x))
+func (n *plainList) Length() (int64, error) {
+	return int64(len(n.x)), nil
 }
 func (plainList) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/map.go b/node/basicnode/map.go
index 9a86fc52..b872a6c8 100644
--- a/node/basicnode/map.go
+++ b/node/basicnode/map.go
@@ -59,8 +59,8 @@ func (n *plainMap) MapIterator() datamodel.MapIterator {
 func (plainMap) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (n *plainMap) Length() int64 {
-	return int64(len(n.t))
+func (n *plainMap) Length() (int64, error) {
+	return int64(len(n.t)), nil
 }
 func (plainMap) IsAbsent() bool {
 	return false
diff --git a/node/basicnode/string.go b/node/basicnode/string.go
index 3d9856c8..1e0bf5e6 100644
--- a/node/basicnode/string.go
+++ b/node/basicnode/string.go
@@ -48,8 +48,8 @@ func (plainString) MapIterator() datamodel.MapIterator {
 func (plainString) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (plainString) Length() int64 {
-	return -1
+func (plainString) Length() (int64, error) {
+	return -1, nil
 }
 func (plainString) IsAbsent() bool {
 	return false
diff --git a/node/bindnode/infer_test.go b/node/bindnode/infer_test.go
index cc7e40d0..ce52348f 100644
--- a/node/bindnode/infer_test.go
+++ b/node/bindnode/infer_test.go
@@ -616,7 +616,11 @@ func useNodeAsKind(node datamodel.Node, asKind datamodel.Kind) error {
 			return err
 		}
 
-		switch l := node.Length(); l {
+		l, err := node.Length()
+		if err != nil {
+			return err
+		}
+		switch l {
 		case 2:
 		case -1:
 			// Return a dummy error to signal whether Length failed.
@@ -657,7 +661,11 @@ func useNodeAsKind(node datamodel.Node, asKind datamodel.Kind) error {
 			return err
 		}
 
-		switch l := node.Length(); l {
+		l, err := node.Length()
+		if err != nil {
+			return err
+		}
+		switch l {
 		case 2:
 		case -1:
 			// Return a dummy error to signal whether Length failed.
diff --git a/node/bindnode/node.go b/node/bindnode/node.go
index 04c1d760..81a1d89a 100644
--- a/node/bindnode/node.go
+++ b/node/bindnode/node.go
@@ -450,21 +450,21 @@ func (w *_node) ListIterator() datamodel.ListIterator {
 	return nil
 }
 
-func (w *_node) Length() int64 {
+func (w *_node) Length() (int64, error) {
 	val := nonPtrVal(w.val)
 	switch w.Kind() {
 	case datamodel.Kind_Map:
 		switch typ := w.schemaType.(type) {
 		case *schema.TypeStruct:
-			return int64(len(typ.Fields()))
+			return int64(len(typ.Fields())), nil
 		case *schema.TypeUnion:
-			return 1
+			return 1, nil
 		}
-		return int64(val.FieldByName("Keys").Len())
+		return int64(val.FieldByName("Keys").Len()), nil
 	case datamodel.Kind_List:
-		return int64(val.Len())
+		return int64(val.Len()), nil
 	}
-	return -1
+	return -1, nil
 }
 
 // TODO: better story around pointers and absent/null
@@ -1647,8 +1647,8 @@ func (_uintNode) MapIterator() datamodel.MapIterator {
 func (_uintNode) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (_uintNode) Length() int64 {
-	return -1
+func (_uintNode) Length() (int64, error) {
+	return -1, nil
 }
 func (_uintNode) IsAbsent() bool {
 	return false
@@ -1705,8 +1705,8 @@ func (_uintNodeRepr) MapIterator() datamodel.MapIterator {
 func (_uintNodeRepr) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (_uintNodeRepr) Length() int64 {
-	return -1
+func (_uintNodeRepr) Length() (int64, error) {
+	return -1, nil
 }
 func (_uintNodeRepr) IsAbsent() bool {
 	return false
diff --git a/node/bindnode/repr.go b/node/bindnode/repr.go
index 3c08a2b8..91f5b695 100644
--- a/node/bindnode/repr.go
+++ b/node/bindnode/repr.go
@@ -425,16 +425,16 @@ func (w *_nodeRepr) lengthMinusTrailingAbsents() int64 {
 	return 0
 }
 
-func (w *_nodeRepr) Length() int64 {
+func (w *_nodeRepr) Length() (int64, error) {
 	switch stg := reprStrategy(w.schemaType).(type) {
 	case schema.StructRepresentation_Stringjoin:
-		return -1
+		return -1, nil
 	case schema.StructRepresentation_Map:
-		return w.lengthMinusAbsents()
+		return w.lengthMinusAbsents(), nil
 	case schema.StructRepresentation_Tuple:
-		return w.lengthMinusTrailingAbsents()
+		return w.lengthMinusTrailingAbsents(), nil
 	case schema.StructRepresentation_ListPairs:
-		return w.lengthMinusAbsents()
+		return w.lengthMinusAbsents(), nil
 	case schema.UnionRepresentation_Keyed:
 		return (*_node)(w).Length()
 	case schema.UnionRepresentation_Kinded:
diff --git a/node/gendemo/ipldsch_satisfaction.go b/node/gendemo/ipldsch_satisfaction.go
index fb60a350..0983c3b6 100644
--- a/node/gendemo/ipldsch_satisfaction.go
+++ b/node/gendemo/ipldsch_satisfaction.go
@@ -74,8 +74,8 @@ func (Bar) MapIterator() datamodel.MapIterator {
 func (Bar) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (Bar) Length() int64 {
-	return -1
+func (Bar) Length() (int64, error) {
+	return -1, nil
 }
 func (Bar) IsAbsent() bool {
 	return false
@@ -283,8 +283,8 @@ func (Baz) MapIterator() datamodel.MapIterator {
 func (Baz) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (Baz) Length() int64 {
-	return -1
+func (Baz) Length() (int64, error) {
+	return -1, nil
 }
 func (Baz) IsAbsent() bool {
 	return false
@@ -488,8 +488,8 @@ func (Foo) MapIterator() datamodel.MapIterator {
 func (Foo) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (Foo) Length() int64 {
-	return -1
+func (Foo) Length() (int64, error) {
+	return -1, nil
 }
 func (Foo) IsAbsent() bool {
 	return false
@@ -693,8 +693,8 @@ func (Int) MapIterator() datamodel.MapIterator {
 func (Int) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (Int) Length() int64 {
-	return -1
+func (Int) Length() (int64, error) {
+	return -1, nil
 }
 func (Int) IsAbsent() bool {
 	return false
@@ -970,8 +970,8 @@ func (itr *_Map__String__Msg3__MapItr) Done() bool {
 func (Map__String__Msg3) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (n Map__String__Msg3) Length() int64 {
-	return int64(len(n.t))
+func (n Map__String__Msg3) Length() (int64, error) {
+	return int64(len(n.t)), nil
 }
 func (Map__String__Msg3) IsAbsent() bool {
 	return false
@@ -1304,8 +1304,8 @@ func (itr *_Map__String__Msg3__ReprMapItr) Done() bool {
 func (_Map__String__Msg3__Repr) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (rn *_Map__String__Msg3__Repr) Length() int64 {
-	return int64(len(rn.t))
+func (rn *_Map__String__Msg3__Repr) Length() (int64, error) {
+	return int64(len(rn.t)), nil
 }
 func (_Map__String__Msg3__Repr) IsAbsent() bool {
 	return false
@@ -1701,8 +1701,8 @@ func (itr *_Msg3__MapItr) Done() bool {
 func (Msg3) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (Msg3) Length() int64 {
-	return 3
+func (Msg3) Length() (int64, error) {
+	return 3, nil
 }
 func (Msg3) IsAbsent() bool {
 	return false
@@ -2194,9 +2194,9 @@ func (itr *_Msg3__ReprMapItr) Done() bool {
 func (_Msg3__Repr) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (rn *_Msg3__Repr) Length() int64 {
+func (rn *_Msg3__Repr) Length() (int64, error) {
 	l := 3
-	return int64(l)
+	return int64(l), nil
 }
 func (_Msg3__Repr) IsAbsent() bool {
 	return false
@@ -2669,8 +2669,8 @@ func (String) MapIterator() datamodel.MapIterator {
 func (String) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (String) Length() int64 {
-	return -1
+func (String) Length() (int64, error) {
+	return -1, nil
 }
 func (String) IsAbsent() bool {
 	return false
@@ -2933,8 +2933,8 @@ func (itr *_UnionKinded__MapItr) Done() bool {
 func (UnionKinded) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (UnionKinded) Length() int64 {
-	return 1
+func (UnionKinded) Length() (int64, error) {
+	return 1, nil
 }
 func (UnionKinded) IsAbsent() bool {
 	return false
@@ -3352,8 +3352,8 @@ func (n *_UnionKinded__Repr) MapIterator() datamodel.MapIterator {
 func (n *_UnionKinded__Repr) ListIterator() datamodel.ListIterator {
 	return nil
 }
-func (n *_UnionKinded__Repr) Length() int64 {
-	return -1
+func (n *_UnionKinded__Repr) Length() (int64, error) {
+	return -1, nil
 }
 func (n *_UnionKinded__Repr) IsAbsent() bool {
 	return false
@@ -3585,7 +3585,11 @@ func (na *_UnionKinded__ReprAssembler) AssignNode(v datamodel.Node) error {
 		v2, _ := v.AsBytes()
 		return na.AssignBytes(v2)
 	case datamodel.Kind_Map:
-		na, err := na.BeginMap(v.Length())
+		l, err := v.Length()
+		if err != nil {
+			return err
+		}
+		na, err := na.BeginMap(l)
 		if err != nil {
 			return err
 		}
@@ -3604,7 +3608,11 @@ func (na *_UnionKinded__ReprAssembler) AssignNode(v datamodel.Node) error {
 		}
 		return na.Finish()
 	case datamodel.Kind_List:
-		na, err := na.BeginList(v.Length())
+		l, err := v.Length()
+		if err != nil {
+			return err
+		}
+		na, err := na.BeginList(l)
 		if err != nil {
 			return err
 		}
diff --git a/node/tests/listSpecs.go b/node/tests/listSpecs.go
index 8dddf10d..0aed325f 100644
--- a/node/tests/listSpecs.go
+++ b/node/tests/listSpecs.go
@@ -18,7 +18,9 @@ func SpecTestListString(t *testing.T, np datamodel.NodePrototype) {
 			la.AssembleValue().AssignString("three")
 		})
 		t.Run("reads back out", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 
 			v, err := n.LookupByIndex(0)
 			qt.Check(t, err, qt.IsNil)
diff --git a/node/tests/mapSpecs.go b/node/tests/mapSpecs.go
index 9aaa9e57..08f5de3a 100644
--- a/node/tests/mapSpecs.go
+++ b/node/tests/mapSpecs.go
@@ -13,7 +13,9 @@ func SpecTestMapStrInt(t *testing.T, np datamodel.NodePrototype) {
 	t.Run("map<str,int>, 3 entries", func(t *testing.T) {
 		n := buildMapStrIntN3(np)
 		t.Run("reads back out", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 
 			v, err := n.LookupByString("whee")
 			qt.Check(t, err, qt.IsNil)
@@ -124,7 +126,9 @@ func SpecTestMapStrInt(t *testing.T, np datamodel.NodePrototype) {
 		// ... and neither of these should've had visible effects!
 		qt.Check(t, ma.Finish(), qt.IsNil)
 		n := nb.Build()
-		qt.Check(t, n.Length(), qt.Equals, int64(1))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(1))
 		v, err := n.LookupByString("whee")
 		qt.Check(t, err, qt.IsNil)
 		v2, err := v.AsInt()
@@ -169,7 +173,9 @@ func SpecTestMapStrMapStrInt(t *testing.T, np datamodel.NodePrototype) {
 		n := nb.Build()
 
 		t.Run("reads back out", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 
 			v, err := n.LookupByString("woot")
 			qt.Check(t, err, qt.IsNil)
@@ -214,7 +220,9 @@ func SpecTestMapStrListStr(t *testing.T, np datamodel.NodePrototype) {
 		n := nb.Build()
 
 		t.Run("reads back out", func(t *testing.T) {
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 
 			v, err := n.LookupByString("qwer")
 			qt.Check(t, err, qt.IsNil)
diff --git a/node/tests/schemaLists.go b/node/tests/schemaLists.go
index bf2945fc..a2fd1c93 100644
--- a/node/tests/schemaLists.go
+++ b/node/tests/schemaLists.go
@@ -33,7 +33,9 @@ func SchemaTestListsContainingMaybe(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 
 				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByIndex(1))), qt.Equals, "2")
@@ -41,13 +43,15 @@ func SchemaTestListsContainingMaybe(t *testing.T, engine Engine) {
 				qt.Check(t, must.String(must.Node(n.LookupBySegment(datamodel.PathSegmentOfInt(0)))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByNode(basicnode.NewInt(0)))), qt.Equals, "1")
 
-				_, err := n.LookupByIndex(3)
+				_, err = n.LookupByIndex(3)
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(1))), qt.Equals, "2")
@@ -55,7 +59,7 @@ func SchemaTestListsContainingMaybe(t *testing.T, engine Engine) {
 				qt.Check(t, must.String(must.Node(n.LookupBySegment(datamodel.PathSegmentOfInt(0)))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByNode(basicnode.NewInt(0)))), qt.Equals, "1")
 
-				_, err := n.LookupByIndex(3)
+				_, err = n.LookupByIndex(3)
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 		})
@@ -78,19 +82,23 @@ func SchemaTestListsContainingMaybe(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.Node(n.LookupByIndex(1)), qt.Equals, datamodel.Null)
-				_, err := n.LookupByIndex(3)
+				_, err = n.LookupByIndex(3)
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.Node(n.LookupByIndex(1)), qt.Equals, datamodel.Null)
-				_, err := n.LookupByIndex(3)
+				_, err = n.LookupByIndex(3)
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 		})
@@ -147,10 +155,18 @@ func SchemaTestListsContainingLists(t *testing.T, engine Engine) {
 		}).(schema.TypedNode)
 		t.Run("typed-read", func(t *testing.T) {
 			qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-			qt.Assert(t, n.Length(), qt.Equals, int64(3))
-			qt.Assert(t, must.Node(n.LookupByIndex(0)).Length(), qt.Equals, int64(3))
-			qt.Assert(t, must.Node(n.LookupByIndex(1)).Length(), qt.Equals, int64(1))
-			qt.Assert(t, must.Node(n.LookupByIndex(2)).Length(), qt.Equals, int64(2))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(3))
+			l, err = must.Node(n.LookupByIndex(0)).Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(3))
+			l, err = must.Node(n.LookupByIndex(1)).Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(1))
+			l, err = must.Node(n.LookupByIndex(2)).Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(2))
 
 			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(0)).LookupByString("field"))), qt.Equals, "11")
 			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(2)).LookupByString("field"))), qt.Equals, "13")
@@ -160,10 +176,18 @@ func SchemaTestListsContainingLists(t *testing.T, engine Engine) {
 		t.Run("repr-read", func(t *testing.T) {
 			nr := n.Representation()
 			qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-			qt.Assert(t, nr.Length(), qt.Equals, int64(3))
-			qt.Assert(t, must.Node(nr.LookupByIndex(0)).Length(), qt.Equals, int64(3))
-			qt.Assert(t, must.Node(nr.LookupByIndex(1)).Length(), qt.Equals, int64(1))
-			qt.Assert(t, must.Node(nr.LookupByIndex(2)).Length(), qt.Equals, int64(2))
+			l, err := nr.Length()
+			qt.Assert(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(3))
+			l, err = must.Node(nr.LookupByIndex(0)).Length()
+			qt.Assert(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(3))
+			l, err = must.Node(nr.LookupByIndex(1)).Length()
+			qt.Assert(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(1))
+			l, err = must.Node(nr.LookupByIndex(2)).Length()
+			qt.Assert(t, err, qt.IsNil)
+			qt.Assert(t, l, qt.Equals, int64(2))
 
 			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(0)).LookupByString("encoded"))), qt.Equals, "11")
 			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(2)).LookupByString("encoded"))), qt.Equals, "13")
diff --git a/node/tests/schemaMaps.go b/node/tests/schemaMaps.go
index b804870a..7b779df9 100644
--- a/node/tests/schemaMaps.go
+++ b/node/tests/schemaMaps.go
@@ -32,19 +32,23 @@ func SchemaTestMapsContainingMaybe(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByString("one"))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByString("two"))), qt.Equals, "2")
-				_, err := n.LookupByString("miss")
+				_, err = n.LookupByString("miss")
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(nr.LookupByString("one"))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(nr.LookupByString("two"))), qt.Equals, "2")
-				_, err := nr.LookupByString("miss")
+				_, err = nr.LookupByString("miss")
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 		})
@@ -67,19 +71,23 @@ func SchemaTestMapsContainingMaybe(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByString("one"))), qt.Equals, "1")
 				qt.Check(t, must.Node(n.LookupByString("none")), qt.Equals, datamodel.Null)
-				_, err := n.LookupByString("miss")
+				_, err = n.LookupByString("miss")
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(nr.LookupByString("one"))), qt.Equals, "1")
 				qt.Check(t, must.Node(nr.LookupByString("none")), qt.Equals, datamodel.Null)
-				_, err := nr.LookupByString("miss")
+				_, err = nr.LookupByString("miss")
 				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 			})
 		})
@@ -133,33 +141,45 @@ func SchemaTestMapsContainingMaps(t *testing.T, engine Engine) {
 	reading := func(t *testing.T, n datamodel.Node, fieldName string) {
 		withNode(n, func(n datamodel.Node) {
 			qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			withNode(must.Node(n.LookupByString("one")), func(n datamodel.Node) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				withNode(must.Node(n.LookupByString("zot")), func(n datamodel.Node) {
 					qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-					qt.Check(t, n.Length(), qt.Equals, int64(1))
+					l, err := n.Length()
+					qt.Check(t, err, qt.IsNil)
+					qt.Check(t, l, qt.Equals, int64(1))
 					qt.Check(t, must.String(must.Node(n.LookupByString(fieldName))), qt.Equals, "11")
 				})
 				withNode(must.Node(n.LookupByString("zop")), func(n datamodel.Node) {
 					qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-					qt.Check(t, n.Length(), qt.Equals, int64(1))
+					l, err := n.Length()
+					qt.Check(t, err, qt.IsNil)
+					qt.Check(t, l, qt.Equals, int64(1))
 					qt.Check(t, must.String(must.Node(n.LookupByString(fieldName))), qt.Equals, "12")
 				})
 			})
 			withNode(must.Node(n.LookupByString("two")), func(n datamodel.Node) {
-				qt.Check(t, n.Length(), qt.Equals, int64(1))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				withNode(must.Node(n.LookupByString("zim")), func(n datamodel.Node) {
 					qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-					qt.Check(t, n.Length(), qt.Equals, int64(1))
+					l, err := n.Length()
+					qt.Check(t, err, qt.IsNil)
+					qt.Check(t, l, qt.Equals, int64(1))
 					qt.Check(t, must.String(must.Node(n.LookupByString(fieldName))), qt.Equals, "21")
 				})
 			})
 			withNode(must.Node(n.LookupByString("none")), func(n datamodel.Node) {
 				qt.Check(t, n, NodeContentEquals, datamodel.Null)
 			})
-			_, err := n.LookupByString("miss")
+			_, err = n.LookupByString("miss")
 			qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
 		})
 	}
@@ -217,7 +237,9 @@ func SchemaTestMapsWithComplexKeys(t *testing.T, engine Engine) {
 		}).(schema.TypedNode)
 		t.Run("typed-read", func(t *testing.T) {
 			qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-			qt.Check(t, n.Length(), qt.Equals, int64(3))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			n2 := must.Node(n.LookupByString("c:d"))
 			qt.Assert(t, n2.Kind(), qt.Equals, datamodel.Kind_String)
 			qt.Check(t, must.String(n2), qt.Equals, "2")
@@ -225,7 +247,9 @@ func SchemaTestMapsWithComplexKeys(t *testing.T, engine Engine) {
 		t.Run("repr-read", func(t *testing.T) {
 			nr := n.Representation()
 			qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_Map)
-			qt.Check(t, nr.Length(), qt.Equals, int64(3))
+			l, err := nr.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(3))
 			n2 := must.Node(nr.LookupByString("c:d"))
 			qt.Assert(t, n2.Kind(), qt.Equals, datamodel.Kind_String)
 			qt.Check(t, must.String(n2), qt.Equals, "2")
diff --git a/node/tests/schemaScalars.go b/node/tests/schemaScalars.go
index 54d5e1b1..0572ea14 100644
--- a/node/tests/schemaScalars.go
+++ b/node/tests/schemaScalars.go
@@ -138,7 +138,9 @@ func SchemaTestScalars(t *testing.T, engine Engine) {
 						qt.Check(t, err, qt.Not(qt.IsNil))
 						qt.Check(t, n.MapIterator(), qt.IsNil)
 						qt.Check(t, n.ListIterator(), qt.IsNil)
-						qt.Check(t, n.Length(), qt.Equals, int64(-1))
+						l, err := n.Length()
+						qt.Check(t, err, qt.IsNil)
+						qt.Check(t, l, qt.Equals, int64(-1))
 						qt.Check(t, n.IsAbsent(), qt.IsFalse)
 						qt.Check(t, n.IsNull(), qt.IsFalse)
 					})
diff --git a/node/tests/schemaStruct.go b/node/tests/schemaStruct.go
index c614fdf8..6a014b49 100644
--- a/node/tests/schemaStruct.go
+++ b/node/tests/schemaStruct.go
@@ -101,7 +101,9 @@ func SchemaTestStructNesting(t *testing.T, engine Engine) {
 		}).(schema.TypedNode)
 		t.Run("typed-read", func(t *testing.T) {
 			qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-			qt.Check(t, n.Length(), qt.Equals, int64(1))
+			l, err := n.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(1))
 
 			n2 := must.Node(n.LookupByString("x"))
 			qt.Assert(t, n2.Kind(), qt.Equals, datamodel.Kind_Map)
@@ -117,7 +119,9 @@ func SchemaTestStructNesting(t *testing.T, engine Engine) {
 		t.Run("repr-read", func(t *testing.T) {
 			nr := n.Representation()
 			qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_Map)
-			qt.Check(t, nr.Length(), qt.Equals, int64(1))
+			l, err := nr.Length()
+			qt.Check(t, err, qt.IsNil)
+			qt.Check(t, l, qt.Equals, int64(1))
 
 			n2 := must.Node(nr.LookupByString("r"))
 			qt.Assert(t, n2.Kind(), qt.Equals, datamodel.Kind_Map)
diff --git a/node/tests/schemaStructReprListpairs.go b/node/tests/schemaStructReprListpairs.go
index f9e50c19..bae68a6c 100644
--- a/node/tests/schemaStructReprListpairs.go
+++ b/node/tests/schemaStructReprListpairs.go
@@ -51,16 +51,22 @@ func SchemaTestStructReprListPairs(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(1))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				qt.Check(t, must.String(must.Node(n.LookupByString("field"))), qt.Equals, "valoo")
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(1))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				kv := must.Node(nr.LookupByIndex(0))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "field")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "valoo")
 			})
@@ -93,42 +99,58 @@ func SchemaTestStructReprListPairs(t *testing.T, engine Engine) {
 
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(4))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "0")
 				qt.Check(t, must.String(must.Node(n.LookupByString("bar"))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByString("baz"))), qt.Equals, "2")
 				qux := must.Node(n.LookupByString("qux"))
 				qt.Assert(t, qux.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, qux.Length(), qt.Equals, int64(2))
+				l, err = qux.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(0))), qt.Equals, "3")
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(1))), qt.Equals, "4")
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(4))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				kv := must.Node(nr.LookupByIndex(0))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "foo")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "0")
 				kv = must.Node(nr.LookupByIndex(1))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "bar")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "1")
 				kv = must.Node(nr.LookupByIndex(2))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "baz")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "2")
 				kv = must.Node(nr.LookupByIndex(3))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "qux")
 				qux := must.Node(kv.LookupByIndex(1))
 				qt.Assert(t, qux.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, qux.Length(), qt.Equals, int64(2))
+				l, err = qux.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(0))), qt.Equals, "3")
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(1))), qt.Equals, "4")
 			})
@@ -197,32 +219,44 @@ func SchemaTestStructReprListPairs(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(4))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				qt.Check(t, must.Node(n.LookupByString("foo")), qt.Equals, datamodel.Null)
 				qt.Check(t, must.Node(n.LookupByString("bar")), qt.Equals, datamodel.Absent)
 				qt.Check(t, must.Node(n.LookupByString("baz")), qt.Equals, datamodel.Absent)
 				qux := must.Node(n.LookupByString("qux"))
 				qt.Assert(t, qux.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, qux.Length(), qt.Equals, int64(2))
+				l, err = qux.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(1))), qt.Equals, "2")
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				kv := must.Node(nr.LookupByIndex(0))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "foo")
 				qt.Check(t, must.Node(kv.LookupByIndex(1)), qt.Equals, datamodel.Null)
 				kv = must.Node(nr.LookupByIndex(1))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "qux")
 				qux := must.Node(kv.LookupByIndex(1))
 				qt.Assert(t, qux.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, qux.Length(), qt.Equals, int64(2))
+				l, err = qux.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(0))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(qux.LookupByIndex(1))), qt.Equals, "2")
 			})
@@ -278,7 +312,9 @@ func SchemaTestStructReprListPairs(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByString("str"))), qt.Equals, "boop")
 				lp := must.Node(n.LookupByString("lp"))
 				qt.Check(t, lp.Kind(), qt.Equals, datamodel.Kind_Map)
@@ -287,20 +323,28 @@ func SchemaTestStructReprListPairs(t *testing.T, engine Engine) {
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				kv := must.Node(nr.LookupByIndex(0))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "str")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "boop")
 				kv = must.Node(nr.LookupByIndex(1))
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "lp")
 				lp := must.Node(kv.LookupByIndex(1))
 				qt.Check(t, lp.Kind(), qt.Equals, datamodel.Kind_List)
 				kv = must.Node(lp.LookupByIndex(0))
-				qt.Check(t, kv.Length(), qt.Equals, int64(2))
+				l, err = kv.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(0))), qt.Equals, "field")
 				qt.Check(t, must.String(must.Node(kv.LookupByIndex(1))), qt.Equals, "valoo")
 			})
diff --git a/node/tests/schemaStructReprStringjoin.go b/node/tests/schemaStructReprStringjoin.go
index 7684ca7d..9a8c3dad 100644
--- a/node/tests/schemaStructReprStringjoin.go
+++ b/node/tests/schemaStructReprStringjoin.go
@@ -52,7 +52,9 @@ func SchemaTestStructReprStringjoin(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(1))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				qt.Check(t, must.String(must.Node(n.LookupByString("field"))), qt.Equals, "valoo")
 			})
 			t.Run("repr-read", func(t *testing.T) {
@@ -80,7 +82,9 @@ func SchemaTestStructReprStringjoin(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "v1")
 				qt.Check(t, must.String(must.Node(n.LookupByString("bar"))), qt.Equals, "v2")
 			})
@@ -109,7 +113,9 @@ func SchemaTestStructReprStringjoin(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(2))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "")
 				qt.Check(t, must.String(must.Node(n.LookupByString("bar"))), qt.Equals, "v2")
 			})
@@ -142,11 +148,15 @@ func SchemaTestStructReprStringjoin(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(3))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(3))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "v1")
 				qt.Check(t, must.String(must.Node(n.LookupByString("bar"))), qt.Equals, "v4")
 				n2 := must.Node(n.LookupByString("zap"))
-				qt.Check(t, n2.Length(), qt.Equals, int64(2))
+				l, err = n2.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(n2.LookupByString("foo"))), qt.Equals, "v2")
 				qt.Check(t, must.String(must.Node(n2.LookupByString("bar"))), qt.Equals, "v3")
 			})
diff --git a/node/tests/schemaStructReprTuple.go b/node/tests/schemaStructReprTuple.go
index e57cae7c..9e8de308 100644
--- a/node/tests/schemaStructReprTuple.go
+++ b/node/tests/schemaStructReprTuple.go
@@ -42,13 +42,17 @@ func SchemaTestStructReprTuple(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(1))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				qt.Check(t, must.String(must.Node(n.LookupByString("field"))), qt.Equals, "valoo")
 			})
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(1))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(1))
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(0))), qt.Equals, "valoo")
 			})
 		})
@@ -73,7 +77,9 @@ func SchemaTestStructReprTuple(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(4))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "0")
 				qt.Check(t, must.String(must.Node(n.LookupByString("bar"))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(n.LookupByString("baz"))), qt.Equals, "2")
@@ -82,7 +88,9 @@ func SchemaTestStructReprTuple(t *testing.T, engine Engine) {
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(4))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(0))), qt.Equals, "0")
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(1))), qt.Equals, "1")
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(2))), qt.Equals, "2")
@@ -111,7 +119,9 @@ func SchemaTestStructReprTuple(t *testing.T, engine Engine) {
 			}).(schema.TypedNode)
 			t.Run("typed-read", func(t *testing.T) {
 				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_Map)
-				qt.Check(t, n.Length(), qt.Equals, int64(4))
+				l, err := n.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(4))
 				qt.Check(t, must.String(must.Node(n.LookupByString("foo"))), qt.Equals, "0")
 				qt.Check(t, must.Node(n.LookupByString("bar")), qt.Equals, datamodel.Null)
 				qt.Check(t, must.Node(n.LookupByString("baz")), qt.Equals, datamodel.Absent)
@@ -120,7 +130,9 @@ func SchemaTestStructReprTuple(t *testing.T, engine Engine) {
 			t.Run("repr-read", func(t *testing.T) {
 				nr := n.Representation()
 				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
-				qt.Check(t, nr.Length(), qt.Equals, int64(2))
+				l, err := nr.Length()
+				qt.Check(t, err, qt.IsNil)
+				qt.Check(t, l, qt.Equals, int64(2))
 				qt.Check(t, must.String(must.Node(nr.LookupByIndex(0))), qt.Equals, "0")
 				qt.Check(t, must.Node(nr.LookupByIndex(1)), qt.Equals, datamodel.Null)
 			})
diff --git a/node/tests/testcase.go b/node/tests/testcase.go
index 0273784d..d4064b2f 100644
--- a/node/tests/testcase.go
+++ b/node/tests/testcase.go
@@ -208,7 +208,11 @@ func (tcase testcase) Test(t *testing.T, np, npr datamodel.NodePrototype) {
 
 func shallowCopyMap(np datamodel.NodePrototype, n datamodel.Node) (datamodel.Node, error) {
 	nb := np.NewBuilder()
-	ma, err := nb.BeginMap(n.Length())
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
+	ma, err := nb.BeginMap(l)
 	if err != nil {
 		return nil, err
 	}
diff --git a/printer/printer.go b/printer/printer.go
index 55cb6bc1..927e12a8 100644
--- a/printer/printer.go
+++ b/printer/printer.go
@@ -233,7 +233,11 @@ func (z *printBuf) doString(indentLevel int, printState uint8, n datamodel.Node)
 				childState = printState_isCmplxValue
 			}
 			z.writeString("{")
-			if !oneline && n.Length() > 0 {
+			l, err := n.Length()
+			if err != nil {
+				panic(err)
+			}
+			if !oneline && l > 0 {
 				z.writeString("\n")
 			}
 			for itr := n.MapIterator(); !itr.Done(); {
@@ -294,7 +298,11 @@ func (z *printBuf) doString(indentLevel int, printState uint8, n datamodel.Node)
 			childKeyState = printState_isCmplxKey
 		}
 		z.writeString("{")
-		if n.Length() > 0 {
+		l, err := n.Length()
+		if err != nil {
+			panic(err)
+		}
+		if l > 0 {
 			z.writeString("\n")
 		} else {
 			z.writeString("}")
@@ -318,7 +326,11 @@ func (z *printBuf) doString(indentLevel int, printState uint8, n datamodel.Node)
 		z.writeString("}")
 	case datamodel.Kind_List:
 		z.writeString("{")
-		if n.Length() > 0 {
+		l, err := n.Length()
+		if err != nil {
+			panic(err)
+		}
+		if l > 0 {
 			z.writeString("\n")
 		} else {
 			z.writeString("}")
diff --git a/printer/printer_test.go b/printer/printer_test.go
index 9a53b617..8c5a0906 100644
--- a/printer/printer_test.go
+++ b/printer/printer_test.go
@@ -273,8 +273,8 @@ func (n nilTypedNode) ListIterator() datamodel.ListIterator {
 	return nil
 }
 
-func (n nilTypedNode) Length() int64 {
-	return 0
+func (n nilTypedNode) Length() (int64, error) {
+	return 0, nil
 }
 
 func (n nilTypedNode) IsAbsent() bool {
diff --git a/schema/gen/go/genList.go b/schema/gen/go/genList.go
index 390a80c9..b9f60264 100644
--- a/schema/gen/go/genList.go
+++ b/schema/gen/go/genList.go
@@ -42,7 +42,9 @@ func (g listGenerator) EmitNativeAccessors(w io.Writer) {
 	//    and may additionally incur a memcpy if the maybe for the value type doesn't use pointers internally).
 	doTemplate(`
 		func (n *_{{ .Type | TypeSymbol }}) Lookup(idx int64) {{ .Type.ValueType | TypeSymbol }} {
-			if n.Length() <= idx {
+			if l, err := n.Length(); err != nil {
+				return nil
+			} else if l <= idx {
 				return nil
 			}
 			v := &n.x[idx]
@@ -56,7 +58,9 @@ func (g listGenerator) EmitNativeAccessors(w io.Writer) {
 			{{- end}}
 		}
 		func (n *_{{ .Type | TypeSymbol }}) LookupMaybe(idx int64) Maybe{{ .Type.ValueType | TypeSymbol }} {
-			if n.Length() <= idx {
+			if l, err := n.Length(); err != nil {
+				return nil
+			} else if l <= idx {
 				return nil
 			}
 			v := &n.x[idx]
@@ -145,7 +149,9 @@ func (g listGenerator) EmitNodeTypeAssertions(w io.Writer) {
 func (g listGenerator) EmitNodeMethodLookupByIndex(w io.Writer) {
 	doTemplate(`
 		func (n {{ .Type | TypeSymbol }}) LookupByIndex(idx int64) (datamodel.Node, error) {
-			if n.Length() <= idx {
+			if l, err := n.Length(); err != nil {
+				return nil, err
+			} else if l <= idx {
 				return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
 			}
 			v := &n.x[idx]
@@ -214,8 +220,8 @@ func (g listGenerator) EmitNodeMethodListIterator(w io.Writer) {
 
 func (g listGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func (n {{ .Type | TypeSymbol }}) Length() int64 {
-			return int64(len(n.x))
+		func (n {{ .Type | TypeSymbol }}) Length() (int64, error) {
+			return int64(len(n.x)), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genListReprList.go b/schema/gen/go/genListReprList.go
index d17a7e7f..0829c3d6 100644
--- a/schema/gen/go/genListReprList.go
+++ b/schema/gen/go/genListReprList.go
@@ -120,8 +120,8 @@ func (g listReprListReprGenerator) EmitNodeMethodListIterator(w io.Writer) {
 
 func (g listReprListReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() int64 {
-			return int64(len(rn.x))
+		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() (int64, error) {
+			return int64(len(rn.x)), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genMap.go b/schema/gen/go/genMap.go
index 6dc496ec..10e1eb46 100644
--- a/schema/gen/go/genMap.go
+++ b/schema/gen/go/genMap.go
@@ -259,8 +259,8 @@ func (g mapGenerator) EmitNodeMethodMapIterator(w io.Writer) {
 
 func (g mapGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func (n {{ .Type | TypeSymbol }}) Length() int64 {
-			return int64(len(n.t))
+		func (n {{ .Type | TypeSymbol }}) Length() (int64, error) {
+			return int64(len(n.t)), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genMapReprMap.go b/schema/gen/go/genMapReprMap.go
index 977fc1a6..06614499 100644
--- a/schema/gen/go/genMapReprMap.go
+++ b/schema/gen/go/genMapReprMap.go
@@ -115,8 +115,8 @@ func (g mapReprMapReprGenerator) EmitNodeMethodMapIterator(w io.Writer) {
 }
 func (g mapReprMapReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() int64 {
-			return int64(len(rn.t))
+		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() (int64, error) {
+			return int64(len(rn.t)), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genStruct.go b/schema/gen/go/genStruct.go
index 1351eb3c..65f5cd17 100644
--- a/schema/gen/go/genStruct.go
+++ b/schema/gen/go/genStruct.go
@@ -193,8 +193,8 @@ func (g structGenerator) EmitNodeMethodMapIterator(w io.Writer) {
 
 func (g structGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func ({{ .Type | TypeSymbol }}) Length() int64 {
-			return {{ len .Type.Fields }}
+		func ({{ .Type | TypeSymbol }}) Length() (int64, error) {
+			return {{ len .Type.Fields }}, nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genStructReprMap.go b/schema/gen/go/genStructReprMap.go
index 368a3111..417506e8 100644
--- a/schema/gen/go/genStructReprMap.go
+++ b/schema/gen/go/genStructReprMap.go
@@ -244,7 +244,7 @@ func (g structReprMapReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	// This is fun: it has to count down for any unset optional fields.
 	// TODO : support for implicits is still future work.
 	doTemplate(`
-		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() int64 {
+		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() (int64, error) {
 			l := {{ len .Type.Fields }}
 			{{- range $field := .Type.Fields }}
 			{{- if $field.IsOptional }}
@@ -253,7 +253,7 @@ func (g structReprMapReprGenerator) EmitNodeMethodLength(w io.Writer) {
 			}
 			{{- end}}
 			{{- end}}
-			return int64(l)
+			return int64(l), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genStructReprTuple.go b/schema/gen/go/genStructReprTuple.go
index f4a255ff..0c699a78 100644
--- a/schema/gen/go/genStructReprTuple.go
+++ b/schema/gen/go/genStructReprTuple.go
@@ -223,7 +223,7 @@ func (g structReprTupleReprGenerator) EmitNodeMethodListIterator(w io.Writer) {
 func (g structReprTupleReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	// This is fun: it has to count down for any unset optional fields.
 	doTemplate(`
-		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() int64 {
+		func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() (int64, error) {
 			l := {{ len .Type.Fields }}
 			{{- range $field := .Type.Fields }}
 			{{- if $field.IsOptional }}
@@ -232,7 +232,7 @@ func (g structReprTupleReprGenerator) EmitNodeMethodLength(w io.Writer) {
 			}
 			{{- end}}
 			{{- end}}
-			return int64(l)
+			return int64(l), nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genUnion.go b/schema/gen/go/genUnion.go
index a185bbfd..00dca8db 100644
--- a/schema/gen/go/genUnion.go
+++ b/schema/gen/go/genUnion.go
@@ -231,8 +231,8 @@ func (g unionGenerator) EmitNodeMethodMapIterator(w io.Writer) {
 
 func (g unionGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func ({{ .Type | TypeSymbol }}) Length() int64 {
-			return 1
+		func ({{ .Type | TypeSymbol }}) Length() (int64, error) {
+			return 1, nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genUnionReprKeyed.go b/schema/gen/go/genUnionReprKeyed.go
index c2af0253..c4c302a1 100644
--- a/schema/gen/go/genUnionReprKeyed.go
+++ b/schema/gen/go/genUnionReprKeyed.go
@@ -160,8 +160,8 @@ func (g unionReprKeyedReprGenerator) EmitNodeMethodMapIterator(w io.Writer) {
 
 func (g unionReprKeyedReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(`
-		func (_{{ .Type | TypeSymbol }}__Repr) Length() int64 {
-			return 1
+		func (_{{ .Type | TypeSymbol }}__Repr) Length() (int64, error) {
+			return 1, nil
 		}
 	`, w, g.AdjCfg, g)
 }
diff --git a/schema/gen/go/genUnionReprKinded.go b/schema/gen/go/genUnionReprKinded.go
index 6fe32f1a..04b8a2cd 100644
--- a/schema/gen/go/genUnionReprKinded.go
+++ b/schema/gen/go/genUnionReprKinded.go
@@ -228,12 +228,12 @@ func (g unionKindedReprGenerator) EmitNodeMethodListIterator(w io.Writer) {
 func (g unionKindedReprGenerator) EmitNodeMethodLength(w io.Writer) {
 	doTemplate(kindedUnionNodeMethodTemplateMunge(
 		`Length`,
-		`Length() int64`,
+		`Length() (int64, error)`,
 		`{{- if or (.Type.RepresentationStrategy.GetMember (Kind "map")) (.Type.RepresentationStrategy.GetMember (Kind "list")) }}`,
 		`{{- if or (eq $member.RepresentationBehavior.String "map") (eq $member.RepresentationBehavior.String "list") }}`,
 		`.Length()`,
 		`datamodel.KindSet_Recursive`,
-		`-1`,
+		`-1, nil`,
 		true,
 	), w, g.AdjCfg, g)
 }
@@ -590,7 +590,11 @@ func (g unionKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.
 				v2, _ := v.AsBytes()
 				return na.AssignBytes(v2)
 			case datamodel.Kind_Map:
-				na, err := na.BeginMap(v.Length())
+				l, err := v.Length()
+				if err != nil {
+					return err
+				}
+				na, err := na.BeginMap(l)
 				if err != nil {
 					return err
 				}
@@ -609,7 +613,11 @@ func (g unionKindedReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.
 				}
 				return na.Finish()
 			case datamodel.Kind_List:
-				na, err := na.BeginList(v.Length())
+				l, err := v.Length()
+				if err != nil {
+					return err
+				}
+				na, err := na.BeginList(l)
 				if err != nil {
 					return err
 				}
diff --git a/schema/gen/go/mixins/kindTraits.go b/schema/gen/go/mixins/kindTraits.go
index 61bf3c89..72f8ec1c 100644
--- a/schema/gen/go/mixins/kindTraits.go
+++ b/schema/gen/go/mixins/kindTraits.go
@@ -102,8 +102,8 @@ func (g kindTraitsGenerator) emitNodeMethodLength(w io.Writer) {
 		panic("gen internals error: you should've overriden this")
 	}
 	doTemplate(`
-		func ({{ .TypeSymbol }}) Length() int64 {
-			return -1
+		func ({{ .TypeSymbol }}) Length() (int64, error) {
+			return -1, nil
 		}
 	`, w, g)
 }
diff --git a/traversal/focus.go b/traversal/focus.go
index 225a0994..2ccf010a 100644
--- a/traversal/focus.go
+++ b/traversal/focus.go
@@ -252,7 +252,11 @@ func (prog Progress) focusedTransform(n datamodel.Node, na datamodel.NodeAssembl
 	//   so we only get to this case if we were expecting to go deeper.
 	switch n.Kind() {
 	case datamodel.Kind_Map:
-		ma, err := na.BeginMap(n.Length())
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
+		ma, err := na.BeginMap(l)
 		if err != nil {
 			return err
 		}
@@ -332,7 +336,11 @@ func (prog Progress) focusedTransform(n datamodel.Node, na datamodel.NodeAssembl
 		}
 		return ma.Finish()
 	case datamodel.Kind_List:
-		la, err := na.BeginList(n.Length())
+		l, err := n.Length()
+		if err != nil {
+			return err
+		}
+		la, err := na.BeginList(l)
 		if err != nil {
 			return err
 		}
@@ -374,7 +382,11 @@ func (prog Progress) focusedTransform(n datamodel.Node, na datamodel.NodeAssembl
 		if ti >= 0 {
 			return fmt.Errorf("transform: cannot navigate path segment %q at %q because it is beyond the list bounds", seg, prog.Path)
 		}
-		prog.Path = prog.Path.AppendSegment(datamodel.PathSegmentOfInt(n.Length()))
+		nl, err := n.Length()
+		if err != nil {
+			return err
+		}
+		prog.Path = prog.Path.AppendSegment(datamodel.PathSegmentOfInt(nl))
 		if err := prog.focusedTransform(nil, la.AssembleValue(), p2, fn, createParents); err != nil {
 			return err
 		}
diff --git a/traversal/focus_test.go b/traversal/focus_test.go
index 7467a8e8..15b904c0 100644
--- a/traversal/focus_test.go
+++ b/traversal/focus_test.go
@@ -277,7 +277,9 @@ func TestFocusedTransform(t *testing.T) {
 		// updated value should be there
 		qt.Check(t, must.Node(n.LookupByIndex(2)), nodetests.NodeContentEquals, basicnode.NewString("new string!"))
 		// everything else should be there
-		qt.Check(t, n.Length(), qt.Equals, int64(4))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(4))
 		qt.Check(t, must.Node(n.LookupByIndex(0)), nodetests.NodeContentEquals, basicnode.NewLink(leafAlphaLnk))
 		qt.Check(t, must.Node(n.LookupByIndex(1)), nodetests.NodeContentEquals, basicnode.NewLink(leafAlphaLnk))
 		qt.Check(t, must.Node(n.LookupByIndex(3)), nodetests.NodeContentEquals, basicnode.NewLink(leafAlphaLnk))
@@ -293,7 +295,9 @@ func TestFocusedTransform(t *testing.T) {
 		// updated value should be there
 		qt.Check(t, must.Node(n.LookupByIndex(4)), nodetests.NodeContentEquals, basicnode.NewString("new string!"))
 		// everything else should be there
-		qt.Check(t, n.Length(), qt.Equals, int64(5))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(5))
 	})
 	t.Run("ListBounds", func(t *testing.T) {
 		_, err := traversal.FocusedTransform(middleListNode, datamodel.ParsePath("4"), func(progress traversal.Progress, prev datamodel.Node) (datamodel.Node, error) {
@@ -313,7 +317,9 @@ func TestFocusedTransform(t *testing.T) {
 		}, false)
 		qt.Check(t, err, qt.IsNil)
 		qt.Check(t, n.Kind(), qt.Equals, datamodel.Kind_List)
-		qt.Check(t, n.Length(), qt.Equals, int64(0))
+		l, err := n.Length()
+		qt.Check(t, err, qt.IsNil)
+		qt.Check(t, l, qt.Equals, int64(0))
 	})
 }
 
@@ -367,7 +373,11 @@ func TestFocusedTransformWithLinks(t *testing.T) {
 }
 
 func keys(n datamodel.Node) []string {
-	v := make([]string, 0, n.Length())
+	l, err := n.Length()
+	if err != nil {
+		panic(err)
+	}
+	v := make([]string, 0, l)
 	for itr := n.MapIterator(); !itr.Done(); {
 		k, _, _ := itr.Next()
 		v = append(v, must.String(k))
diff --git a/traversal/patch/eval.go b/traversal/patch/eval.go
index 9534033c..c8e1b3f5 100644
--- a/traversal/patch/eval.go
+++ b/traversal/patch/eval.go
@@ -64,7 +64,11 @@ func EvalOne(n datamodel.Node, op Operation) (datamodel.Node, error) {
 				}
 
 				nb := parent.Prototype().NewBuilder()
-				la, err := nb.BeginList(parent.Length() + 1)
+				pl, err := parent.Length()
+				if err != nil {
+					return nil, err
+				}
+				la, err := nb.BeginList(pl + 1)
 				if err != nil {
 					return nil, err
 				}
diff --git a/traversal/selector/condition.go b/traversal/selector/condition.go
index 3d59cf49..01da54c0 100644
--- a/traversal/selector/condition.go
+++ b/traversal/selector/condition.go
@@ -55,7 +55,11 @@ func (pc ParseContext) ParseCondition(n datamodel.Node) (Condition, error) {
 	if n.Kind() != datamodel.Kind_Map {
 		return Condition{}, fmt.Errorf("selector spec parse rejected: condition body must be a map")
 	}
-	if n.Length() != 1 {
+	l, err := n.Length()
+	if err != nil {
+		return Condition{}, err
+	}
+	if l != 1 {
 		return Condition{}, fmt.Errorf("selector spec parse rejected: condition is a keyed union and thus must be single-entry map")
 	}
 	kn, v, _ := n.MapIterator().Next()
diff --git a/traversal/selector/exploreFields.go b/traversal/selector/exploreFields.go
index b2796ff2..1be9d8bd 100644
--- a/traversal/selector/exploreFields.go
+++ b/traversal/selector/exploreFields.go
@@ -56,9 +56,13 @@ func (pc ParseContext) ParseExploreFields(n datamodel.Node) (Selector, error) {
 	if fields.Kind() != datamodel.Kind_Map {
 		return nil, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be a map")
 	}
+	fl, err := fields.Length()
+	if err != nil {
+		return nil, err
+	}
 	x := ExploreFields{
-		make(map[string]Selector, fields.Length()),
-		make([]datamodel.PathSegment, 0, fields.Length()),
+		make(map[string]Selector, fl),
+		make([]datamodel.PathSegment, 0, fl),
 	}
 	for itr := fields.MapIterator(); !itr.Done(); {
 		kn, v, err := itr.Next()
diff --git a/traversal/selector/exploreRecursive.go b/traversal/selector/exploreRecursive.go
index 28a9bedc..b35e41c2 100644
--- a/traversal/selector/exploreRecursive.go
+++ b/traversal/selector/exploreRecursive.go
@@ -235,7 +235,11 @@ func parseLimit(n datamodel.Node) (RecursionLimit, error) {
 	if n.Kind() != datamodel.Kind_Map {
 		return RecursionLimit{}, fmt.Errorf("selector spec parse rejected: limit in ExploreRecursive is a keyed union and thus must be a map")
 	}
-	if n.Length() != 1 {
+	l, err := n.Length()
+	if err != nil {
+		return RecursionLimit{}, err
+	}
+	if l != 1 {
 		return RecursionLimit{}, fmt.Errorf("selector spec parse rejected: limit in ExploreRecursive is a keyed union and thus must be a single-entry map")
 	}
 	kn, v, _ := n.MapIterator().Next()
diff --git a/traversal/selector/exploreUnion.go b/traversal/selector/exploreUnion.go
index 21594954..6ded0b1a 100644
--- a/traversal/selector/exploreUnion.go
+++ b/traversal/selector/exploreUnion.go
@@ -92,8 +92,12 @@ func (pc ParseContext) ParseExploreUnion(n datamodel.Node) (Selector, error) {
 	if n.Kind() != datamodel.Kind_List {
 		return nil, fmt.Errorf("selector spec parse rejected: explore union selector must be a list")
 	}
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
 	x := ExploreUnion{
-		make([]Selector, 0, n.Length()),
+		make([]Selector, 0, l),
 	}
 	for itr := n.ListIterator(); !itr.Done(); {
 		_, v, err := itr.Next()
diff --git a/traversal/selector/selector.go b/traversal/selector/selector.go
index b58fcd86..dfb5567a 100644
--- a/traversal/selector/selector.go
+++ b/traversal/selector/selector.go
@@ -150,7 +150,11 @@ func (pc ParseContext) ParseSelector(n datamodel.Node) (Selector, error) {
 	if n.Kind() != datamodel.Kind_Map {
 		return nil, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")
 	}
-	if n.Length() != 1 {
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
+	if l != 1 {
 		return nil, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be single-entry map")
 	}
 	kn, v, _ := n.MapIterator().Next()
diff --git a/traversal/walk.go b/traversal/walk.go
index 1bd4e6c2..06ea3a86 100644
--- a/traversal/walk.go
+++ b/traversal/walk.go
@@ -514,7 +514,11 @@ func contains(interest []datamodel.PathSegment, candidate datamodel.PathSegment)
 
 func (prog Progress) walk_transform_iterateList(n datamodel.Node, s selector.Selector, fn TransformFn, attn []datamodel.PathSegment) (datamodel.Node, error) {
 	bldr := n.Prototype().NewBuilder()
-	lstBldr, err := bldr.BeginList(n.Length())
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
+	lstBldr, err := bldr.BeginList(l)
 	if err != nil {
 		return nil, err
 	}
@@ -576,7 +580,11 @@ func (prog Progress) walk_transform_iterateList(n datamodel.Node, s selector.Sel
 
 func (prog Progress) walk_transform_iterateMap(n datamodel.Node, s selector.Selector, fn TransformFn, attn []datamodel.PathSegment) (datamodel.Node, error) {
 	bldr := n.Prototype().NewBuilder()
-	mapBldr, err := bldr.BeginMap(n.Length())
+	l, err := n.Length()
+	if err != nil {
+		return nil, err
+	}
+	mapBldr, err := bldr.BeginMap(l)
 	if err != nil {
 		return nil, err
 	}