Skip to content

Commit 4df2b74

Browse files
authored
feat(firestore): Add FieldNotFoundError for missing fields (googleapis#12899)
This change introduces a new FieldNotFoundError error that is returned when a field is not found in a document. This allows developers to programmatically distinguish between a missing field and other errors, addressing the issue where a generic error was previously returned. Fixes: googleapis#2980
1 parent 011b148 commit 4df2b74

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

firestore/document.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"errors"
1919
"fmt"
2020
"reflect"
21+
"strings"
2122
"time"
2223

2324
pb "cloud.google.com/go/firestore/apiv1/firestorepb"
@@ -26,6 +27,16 @@ import (
2627
tspb "google.golang.org/protobuf/types/known/timestamppb"
2728
)
2829

30+
// FieldNotFoundError is returned by DocumentSnapshot.DataAt and
31+
// DocumentSnapshot.DataAtPath when the given field does not exist.
32+
type FieldNotFoundError struct {
33+
Path string
34+
}
35+
36+
func (e *FieldNotFoundError) Error() string {
37+
return fmt.Sprintf("firestore: no field %q", e.Path)
38+
}
39+
2940
// A DocumentSnapshot contains document data and metadata.
3041
type DocumentSnapshot struct {
3142
// The DocumentRef for this document.
@@ -152,10 +163,10 @@ func (d *DocumentSnapshot) DataAtPath(fp FieldPath) (interface{}, error) {
152163

153164
// valueAtPath returns the value of m referred to by fp.
154165
func valueAtPath(fp FieldPath, m map[string]*pb.Value) (*pb.Value, error) {
155-
for _, k := range fp[:len(fp)-1] {
166+
for i, k := range fp[:len(fp)-1] {
156167
v := m[k]
157168
if v == nil {
158-
return nil, fmt.Errorf("firestore: no field %q", k)
169+
return nil, &FieldNotFoundError{Path: strings.Join(fp[:i+1], ".")}
159170
}
160171
mv := v.GetMapValue()
161172
if mv == nil {
@@ -166,7 +177,7 @@ func valueAtPath(fp FieldPath, m map[string]*pb.Value) (*pb.Value, error) {
166177
k := fp[len(fp)-1]
167178
v := m[k]
168179
if v == nil {
169-
return nil, fmt.Errorf("firestore: no field %q", k)
180+
return nil, &FieldNotFoundError{Path: strings.Join(fp, ".")}
170181
}
171182
return v, nil
172183
}

firestore/document_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package firestore
1616

1717
import (
18+
"errors"
19+
"fmt"
1820
"reflect"
1921
"sort"
2022
"strings"
@@ -337,3 +339,29 @@ func TestExtractTransformPathsErrors(t *testing.T) {
337339
t.Error("got nil, want error")
338340
}
339341
}
342+
343+
func TestDataAtFieldNotFound(t *testing.T) {
344+
_, err := testDoc.DataAt("c")
345+
if err == nil {
346+
t.Fatal("got nil, want error")
347+
}
348+
fmt.Println(err)
349+
var e *FieldNotFoundError
350+
if !errors.As(err, &e) {
351+
t.Fatalf("got error of type %T, want *FieldNotFoundError", err)
352+
}
353+
if e.Path != "c" {
354+
t.Errorf("e.Path = %q; want %q", e.Path, "c")
355+
}
356+
357+
_, err = testDoc.DataAt("b.y")
358+
if err == nil {
359+
t.Fatal("got nil, want error")
360+
}
361+
if !errors.As(err, &e) {
362+
t.Fatalf("got error of type %T, want *FieldNotFoundError", err)
363+
}
364+
if e.Path != "b.y" {
365+
t.Errorf("e.Path = %q; want %q", e.Path, "b.y")
366+
}
367+
}

0 commit comments

Comments
 (0)