google-cloud-go icon indicating copy to clipboard operation
google-cloud-go copied to clipboard

firestore: not returning exact error

Open Jason-SP-Chien opened this issue 2 years ago • 2 comments

Client

Firestore

Code

In firestore/bulkwriter.go, we saw methods of BulkWriter including Create, Delete, Set, and Update. They do not throw the error returned by newXXXWrites. The error itself is replaced by fmt.Errorf("firestore: cannot XXX doc %v", doc.ID), which cost us time to trace out what really happened inside these operations.

Expected behavior

The error itself should be either wrapped or directly returned.

Actual behavior

It is replaced by an almost useless error message.

Jason-SP-Chien avatar Apr 29 '24 08:04 Jason-SP-Chien

@Jason-SP-Chien I was hitting this problem yesterday.

A possible work around is to call the docref.Update() to receive the full details.

	job, err := bulkWriter.Update(ref, update)
	if err != nil {
		// bulkWriter hides the error returned by newUpdatePathWrites,  call Update again to get the error
		_, err = ref.Update(ctx, update)
	}

BulkWriter error

cannot update doc <doc id>

Sample of the improved error for nested map. Passing the same path to update twice to the path { options.style }.

error: field path [options style] cannot be used in the same update as [options style]

Could perform error wrapping to include the Doc ID as well as the detail.

kevpie avatar Jun 12 '24 17:06 kevpie

BulkWriter.Update versus DocumentRef.Update

BulkWriter discards the Error and returns fmt.Errorf("firestore: cannot update doc %v", doc.ID) Could simply wrap it.

// Update adds a document update write to the queue of writes to send.
// Note: You cannot write to (Create, Update, Set, or Delete) the same document more than once.
func (bw *BulkWriter) Update(doc *DocumentRef, updates []Update, preconds ...Precondition) (*BulkWriterJob, error) {
	bw.isOpenLock.RLock()
	defer bw.isOpenLock.RUnlock()
	err := bw.checkWriteConditions(doc)
	if err != nil {
		return nil, err
	}

	w, err := doc.newUpdatePathWrites(updates, preconds)
	if err != nil {
		return nil, fmt.Errorf("firestore: cannot update doc %v", doc.ID)
	}

	if len(w) > 1 {
		return nil, fmt.Errorf("firestore: too many writes sent to bulkwriter")
	}

	j := bw.write(w[0])
	return j, nil
}

DocumentRef.Update returns the provided useful Error detail

// Update updates the document. The values at the given
// field paths are replaced, but other fields of the stored document are untouched.
func (d *DocumentRef) Update(ctx context.Context, updates []Update, preconds ...Precondition) (_ *WriteResult, err error) {
	ctx = trace.StartSpan(ctx, "cloud.google.com/go/firestore.DocumentRef.Update")
	defer func() { trace.EndSpan(ctx, err) }()

	ws, err := d.newUpdatePathWrites(updates, preconds)
	if err != nil {
		return nil, err
	}
	return d.Parent.c.commit1(ctx, ws)
}

Possibly improve the existing error by wrapping

	if err != nil {
		return nil, fmt.Errorf("firestore: cannot update doc %v error: %w", doc.ID, err)
	}

kevpie avatar Jun 12 '24 17:06 kevpie