{"record":{"id":"b66440e78f657014","repo":"apache/beam","slug":"path-to-directory-not-allowed-q","errorCode":null,"errorMessage":"path to directory not allowed: %q","messagePattern":"path to directory not allowed: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/fileio/read.go","lineNumber":121,"sourceCode":"\treturn beam.ParDo(s, newReadFn(option), col)\n}\n\ntype readFn struct {\n\tCompression        compressionType\n\tDirectoryTreatment directoryTreatment\n}\n\nfunc newReadFn(option *readOption) *readFn {\n\treturn &readFn{\n\t\tCompression:        option.Compression,\n\t\tDirectoryTreatment: option.DirectoryTreatment,\n\t}\n}\n\nfunc (fn *readFn) ProcessElement(metadata FileMetadata, emit func(ReadableFile)) error {\n\tif isDirectory(metadata.Path) {\n\t\tif fn.DirectoryTreatment == directoryDisallow {\n\t\t\treturn fmt.Errorf(\"path to directory not allowed: %q\", metadata.Path)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfile := ReadableFile{\n\t\tMetadata:    metadata,\n\t\tCompression: fn.Compression,\n\t}\n\n\temit(file)\n\treturn nil\n}\n\nfunc isDirectory(path string) bool {\n\tif strings.HasSuffix(path, \"/\") || strings.HasSuffix(path, \"\\\\\") {\n\t\treturn true\n\t}\n\treturn false","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/fileio/read.go#L103-L139","documentation":"readFn rejects directory entries when DirectoryTreatment is set to directoryDisallow. MatchAll can expand to directories (e.g. an 'empty glob' match or a directory whose path matched); this DoFn refuses to read them and returns this error instead of silently skipping.","triggerScenarios":"A FileMetadata whose Path is a directory flows into readFn.ProcessElement while the transform was configured with ReadDirectoriesDisallowed (the default disallow behavior).","commonSituations":"Glob patterns like 'dir/*' matched a subdirectory; the user assumed only files would be surfaced; forgot to set ReadDirectoriesPassthrough or filter out directories upstream.","solutions":["Filter out directories before reading (skip entries ending in '/' or check the metadata).","Set the DirectoryTreatment option to allow/passthrough directories if that's intended.","Tighten the match pattern so it doesn't expand to directories.","Add an allowlist of file extensions to the match pattern."],"exampleFix":"// before\np := beam.ParDo(s, &fileio.ReadFn{DirectoryTreatment: fileio.Disallow}, matched)\n// after\np := beam.ParDo(s, &fileio.ReadFn{DirectoryTreatment: fileio.Passthrough}, matched)\n// or filter directories before reading","handlingStrategy":"validation","validationCode":"if strings.HasSuffix(metadata.Path, \"/\") || isDir(metadata.Path) {\n\treturn nil // skip directories before readFn sees them\n}","typeGuard":"func isFile(md FileMetadata) bool { return !strings.HasSuffix(md.Path, \"/\") }","tryCatchPattern":"if err := beam.Run(...); err != nil && strings.Contains(err.Error(), \"path to directory not allowed\") {\n\tlog.Warn(\"match pattern expanded to a directory; filter or set DirectoryTreatment\")\n}","preventionTips":["End glob patterns with an extension filter (e.g. /*.json) to avoid directory matches.","Choose DirectoryTreatment explicitly instead of relying on defaults.","Filter directory entries in the match DoFn before readFn.","Test match patterns against real bucket layouts."],"tags":["go","apache-beam","fileio","validation"],"backgroundTag":"path-is-not-a-directory","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"}