{"record":{"id":"2cec98aebc4c0a1a","repo":"GoogleContainerTools/skaffold","slug":"s-is-a-directory","errorCode":null,"errorMessage":"%s is a directory","messagePattern":"(.+?) is a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/util/util.go","lineNumber":207,"sourceCode":"\t\t\tm[v[0]] = v[1]\n\t\t}\n\t}\n\treturn m\n}\n\nfunc isAlphaNum(c uint8) bool {\n\treturn c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'\n}\n\n// AbsFile resolves the absolute path of the file named filename in directory workspace, erroring if it is not a file\nfunc AbsFile(workspace string, filename string) (string, error) {\n\tfile := filepath.Join(workspace, filename)\n\tinfo, err := os.Stat(file)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif info.IsDir() {\n\t\treturn \"\", fmt.Errorf(\"%s is a directory\", file)\n\t}\n\treturn filepath.Abs(file)\n}\n\n// NonEmptyLines scans the provided input and returns the non-empty strings found as an array\nfunc NonEmptyLines(input []byte) []string {\n\tvar result []string\n\tscanner := bufio.NewScanner(bytes.NewReader(input))\n\tfor scanner.Scan() {\n\t\tif line := scanner.Text(); len(line) > 0 {\n\t\t\tresult = append(result, line)\n\t\t}\n\t}\n\treturn result\n}\n\n// CloneThroughJSON clones an `old` object into a `new` one\n// using json marshalling and unmarshalling.","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/util/util.go#L189-L225","documentation":"AbsFile resolves a filename against a workspace and returns its absolute path, but first stats the path and refuses directories with this error. It is thrown when the provided filename resolves to a directory rather than a regular file. CreateCommand (and tests) use it to validate executable/file inputs before launching commands.","triggerScenarios":"Calling AbsFile (directly or via CreateCommand) with a path that os.Stat reports IsDir — e.g. pointing a command/file config at a directory name, or the workspace + filename join landing on a directory because a filename component was omitted.","commonSituations":"skaffold.yaml referencing a directory where a binary or file is expected (e.g. a custom test command pointing at a folder); a build artifact path that lost its filename during templating; typo making the path resolve to a directory.","solutions":["Point the configuration at the actual file, not its containing directory (e.g. ./script.sh instead of ./scripts).","Verify the resolved path with `ls -la <workspace>/<filename>` — if it is a directory, append the filename.","Check templating/variable substitution isn't dropping the filename portion of the path.","If you intended a directory, use the appropriate config field for directories instead of one requiring a file."],"exampleFix":"// before\ncmd := util.CreateCommand(ctx, \"/work/tools\", \"\", []string{})  // /work/tools is a directory\n// after\ncmd := util.CreateCommand(ctx, \"/work/tools/runner.sh\", \"\", []string{})","handlingStrategy":"validation","validationCode":"func mustBeFile(workspace, name string) error {\n    p := filepath.Join(workspace, name)\n    info, err := os.Stat(p)\n    if err != nil {\n        return err\n    }\n    if info.IsDir() {\n        return fmt.Errorf(\"%q is a directory; expected a file\", p)\n    }\n    return nil\n}","typeGuard":"func isRegularFile(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.Mode().IsRegular()\n}","tryCatchPattern":"abs, err := util.AbsFile(workspace, name)\nif err != nil {\n    if strings.HasSuffix(err.Error(), \"is a directory\") {\n        return fmt.Errorf(\"config points at directory %s; append the filename\", err)\n    }\n    return err\n}","preventionTips":["Point command/file config fields at concrete files, never directories.","Verify paths with `ls -la` or os.Stat.IsDir() in pre-flight checks.","Check templated paths render with the filename included.","If a directory is intended, use the config field designed for directories."],"tags":["filesystem","path","validation","directory"],"backgroundTag":"path-is-a-directory","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}