{"record":{"id":"599f58b0ff6e47c8","repo":"pulumi/pulumi","slug":"cannot-marshal-an-empty-glob","errorCode":null,"errorMessage":"cannot marshal an empty glob","messagePattern":"cannot marshal an empty glob","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdk/go/property/glob.go","lineNumber":42,"sourceCode":"\t\"strings\"\n\n\t\"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract\"\n)\n\ntype Glob struct{ pathRepr }\n\nfunc GlobFromSegments(segments ...GlobSegment) Glob {\n\treturn Glob{pathReprFromSegments(segments)}\n}\n\nvar (\n\t_ encoding.TextMarshaler   = Glob{}\n\t_ encoding.TextUnmarshaler = &Glob{}\n)\n\nfunc (g Glob) MarshalText() (text []byte, err error) {\n\tif g.len() == 0 {\n\t\treturn nil, errors.New(\"cannot marshal an empty glob\")\n\t}\n\tvar b strings.Builder\nsegment:\n\tfor i, p := range g.enumerate {\n\t\tswitch p := p.(type) {\n\t\tcase KeySegment:\n\t\t\tbare := len(p.string) > 0\n\t\t\tfor j, c := range p.string {\n\t\t\t\tif !isPlainPathCharacter(c, j == 0) {\n\t\t\t\t\tbare = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !bare {\n\t\t\t\tfmt.Fprintf(&b, \"[%q]\", p.string)\n\t\t\t\tcontinue segment\n\t\t\t}\n\t\t\tif i != 0 {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/go/property/glob.go#L24-L60","documentation":"property.Glob implements encoding.TextMarshaler; marshaling a Glob that has zero segments (the zero value Glob{}) is rejected because an empty string is not a valid property-path glob representation. The method returns this error instead of emitting an empty byte slice.","triggerScenarios":"Calling Glob.MarshalText() (directly or via encoding/json, yaml, or other TextMarshaler-aware encoders) on a Glob constructed with GlobFromSegments() with no arguments or a zero-value Glob{}.","commonSituations":"Serializing a struct field of type Glob that was never initialized; decoding failures upstream that left the glob empty; building segments conditionally and ending up with none.","solutions":["Ensure the Glob has at least one segment before marshaling: use GlobFromSegments with at least one KeySegment, IndexSegment, or GlobAll segment.","Guard with a check before encoding: skip or substitute a default glob when the value is the zero Glob.","Use a pointer field (*Glob) with nil to represent 'absent' instead of an empty glob."],"exampleFix":"// before\ng := property.GlobFromSegments() // empty\nb, err := g.MarshalText()         // error\n// after\ng := property.GlobFromSegments(property.Key(\"foo\"), property.GlobAll{})\nb, err := g.MarshalText()","handlingStrategy":"validation","validationCode":"func marshalGlobSafe(g property.Glob) ([]byte, error) {\n\tif g == (property.Glob{}) {\n\t\treturn nil, fmt.Errorf(\"glob not initialized\")\n\t}\n\treturn g.MarshalText()\n}","typeGuard":"func isZeroGlob(g property.Glob) bool { return g == property.Glob{} }","tryCatchPattern":"text, err := g.MarshalText()\nif err != nil {\n\tif err.Error() == \"cannot marshal an empty glob\" {\n\t\t// substitute default or skip field\n\t}\n\treturn err\n}","preventionTips":["Never marshal a zero-value Glob; construct with GlobFromSegments and at least one segment.","Model 'absent' globs as *Glob nil instead of empty values.","Initialize Glob fields in struct constructors."],"tags":["go","property-path","glob","serialization","marshaling"],"backgroundTag":"empty-value-marshaling","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}