{"record":{"id":"3dd4d341bccd4e86","repo":"apache/beam","slug":"syntax-error-unclosed-in-pattern-q","errorCode":null,"errorMessage":"syntax error: unclosed '[' in pattern %q","messagePattern":"syntax error: unclosed '\\[' in pattern %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/filesystem/gcs/gcs.go","lineNumber":92,"sourceCode":"\t\t\t} else {\n\t\t\t\tresult.WriteString(\"[^/]*\")\n\t\t\t}\n\t\tcase '?':\n\t\t\tresult.WriteString(\"[^/]\")\n\t\tcase '[':\n\t\t\t// Character class - find the closing bracket\n\t\t\tj := i + 1\n\t\t\tif j < len(runes) && runes[j] == '!' {\n\t\t\t\tj++\n\t\t\t}\n\t\t\tif j < len(runes) && runes[j] == ']' {\n\t\t\t\tj++\n\t\t\t}\n\t\t\tfor j < len(runes) && runes[j] != ']' {\n\t\t\t\tj++\n\t\t\t}\n\t\t\tif j >= len(runes) {\n\t\t\t\treturn nil, fmt.Errorf(\"syntax error: unclosed '[' in pattern %q\", pattern)\n\t\t\t} else {\n\t\t\t\t// Copy the character class, converting ! to ^ for negation\n\t\t\t\tresult.WriteByte('[')\n\t\t\t\tcontent := runes[i+1 : j]\n\t\t\t\tif len(content) > 0 && content[0] == '!' {\n\t\t\t\t\tresult.WriteByte('^')\n\t\t\t\t\tcontent = content[1:]\n\t\t\t\t}\n\t\t\t\tresult.WriteString(string(content))\n\t\t\t\tresult.WriteByte(']')\n\t\t\t\ti = j\n\t\t\t}\n\t\tdefault:\n\t\t\tresult.WriteString(regexp.QuoteMeta(string(c)))\n\t\t}\n\t}\n\n\tresult.WriteString(\"$\") // match end","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/filesystem/gcs/gcs.go#L74-L110","documentation":"The GCS filesystem's custom glob-to-regex converter rejected a pattern containing an unterminated character class: a '[' was opened but no matching ']' was found before the end of the pattern. This is a client-side syntax validation error thrown before any GCS API call.","triggerScenarios":"Calling List (or Match through it) on a GCS filesystem with a glob like 'gs://bucket/data[0-9' where the '[' has no closing ']'.","commonSituations":"Dynamically built patterns with string interpolation truncating the class; user typos; patterns copied from shells where brackets were glob-expanded; escaping mistakes.","solutions":["Add the missing ']' to close the character class in the pattern.","Escape literal '[' as '[[]' if a bracket is intended as a literal character.","Log/print the final pattern before the List call to catch interpolation truncation.","Validate the glob pattern with filesystem.Match or a regex dry-run before calling List."],"exampleFix":"// before\nglob := \"gs://bucket/data[0-9\" // unclosed class\nfiles, err := fs.List(ctx, glob)\n// after\nglob := \"gs://bucket/data[0-9]\" // closed class\nfiles, err := fs.List(ctx, glob)","handlingStrategy":"validation","validationCode":"// validate the bracket classes are balanced before calling List\nfunc validGlob(p string) bool { depth := 0; for _, r := range p { if r == '[' { depth++ }; if r == ']' { depth--; if depth < 0 { return false } } }; return depth == 0 }","typeGuard":null,"tryCatchPattern":"if _, err := fs.List(ctx, glob); err != nil && strings.Contains(err.Error(), `unclosed '['`) {\n\treturn fmt.Errorf(\"bad glob %q: %w\", glob, err)\n}","preventionTips":["Escape literal '[' in patterns.","Print the fully interpolated pattern before List.","Add a glob lint in CI for user-supplied patterns.","Prefer simpler wildcards (*, ?) over character classes when possible."],"tags":["go","apache-beam","gcs","glob","regex"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}