Implementing UnmarshalBSON Truncated Results with no Errors

I wrote a collection struct that pulls data from mongo in the standard way, and a data struct that represents the collections schema. I receive 3611 results from the cursor, and those decode fine. Then, I made an enum (int), and implemented UnmarshalBSON on that type. After replacing a string field in the schema type with that new custom enum type, I silently get 160 results. When I debug, errors are being returned by my UnmarshalBSON function, but cursor.Decode() never surfaces those errors. Is the UnmarshalBSON interface incompatible with the default registry or something?

Hi @Dustin_Currie - welcome to MongoDB Community!

This does sound strange. cursor.Decode() ultimately delegates to Decoder.Decode() - and as far as I can tell that surfaces errors as it should.

Would it be possible to create a small code sample that demonstrates this problem?

I haven’t been able to figure out the problem yet. But, my UnmarshalBSON function is only getting called. 101 times when the struct field is a custom enum. The cursor only outputs those 101 results, without error. When I change the field back to a *string the cursor returns 3662 records.

func ElementTypeFrom(s string) (ElementType, error) {
	for i, e := range elementTypeNames {
		if e == s {
			return ElementType(i), nil
		}
	}
	return ElementType(-1), errors.Errorf("%v is not a valid ElementType", s)
}

func (e *ElementType) UnmarshalBSON(data []byte) error {
	s, err := bsonrw.NewBSONValueReader(bsontype.String, data).ReadString()
	if err != nil {
		return errors.Wrapf(err, "failed to unmarshal %v into element type", string(data))
	}
	et, err := ElementTypeFrom(s)
	if err != nil {
		return errors.Wrap(err, "failed to unmarshal ElementType")
	}
	*e = et
	return nil
}

The important cursor code looks like this:

for cursor.Next(ctx) {
		q := types.MyTypeThatHasAnElementTypeField{}
		if err = cursor.Decode(&q); err != nil || cursor.Err() != nil {
			return nil, errors.Wrapf(err, "failed to decode %v", cursor.Current())
		}
		result = append(result, q)
	}

The was all due to a context cancellation, parallelized goroutines, and my worst copy pasta in the last serveral years. A failed query goroutine was wrapping the nil error of a successful goroutine. That’s why the errors weren’t coming through. Thanks for being a sounding board mongo community.

2 Likes

Hi @Dustin_Currie,

I’m glad to hear that you were able to figure out your issue with cursors and UnmarshalBSON. As always, if you have any driver bug reports or general feedback issues, please feel free to open a ticket in our Jira project (https://jira.mongodb.org/browse/GODRIVER) or a new topic on these forums.

– Divjot

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.