{"record":{"id":"f8bff22b3a9ac061","repo":"go-task/task","slug":"error-reading-env-file-s-w","errorCode":null,"errorMessage":"error reading env file %s: %w","messagePattern":"error reading env file (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"taskfile/dotenv.go","lineNumber":31,"sourceCode":"\nfunc Dotenv(vars *ast.Vars, tf *ast.Taskfile, dir string) (*ast.Vars, error) {\n\tenv := ast.NewVars()\n\tcache := &templater.Cache{Vars: vars}\n\n\tfor _, dotEnvPath := range tf.Dotenv {\n\t\tdotEnvPath = templater.Replace(dotEnvPath, cache)\n\t\tif dotEnvPath == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tdotEnvPath = filepathext.SmartJoin(dir, dotEnvPath)\n\n\t\tif _, err := os.Stat(dotEnvPath); os.IsNotExist(err) {\n\t\t\tcontinue\n\t\t}\n\n\t\tenvs, err := godotenv.Read(dotEnvPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading env file %s: %w\", dotEnvPath, err)\n\t\t}\n\t\tfor key, value := range envs {\n\t\t\tif _, ok := env.Get(key); !ok {\n\t\t\t\tenv.Set(key, ast.Var{Value: value})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn env, nil\n}\n","sourceCodeStart":13,"sourceCodeEnd":42,"githubUrl":"https://github.com/go-task/task/blob/385e5ad92af02877b6d7cf9dcc963b5ed916e70a/taskfile/dotenv.go#L13-L42","documentation":"Task reads .env files listed under `dotenv:` with godotenv.Read. If the file exists but cannot be read or parsed (bad permissions, malformed KEY=VALUE lines), the OS/parser error is wrapped in this message and returned.","triggerScenarios":"readDotEnvFiles -> Dotenv: a dotenv path passes the os.Stat existence check but godotenv.Read fails — e.g. permission denied, path is a directory, or the file has invalid dotenv syntax.","commonSituations":"A .env file with unparseable lines (spaces around =, missing values on quoted lines, junk characters); read-only or root-owned .env in CI; a `dotenv:` entry pointing at a directory instead of a file.","solutions":["Check file permissions so the Task process user can read the file (`chmod 644 .env`)","Fix dotenv syntax: each line must be KEY=VALUE (quote values containing spaces/special chars)","Ensure the dotenv path points to a regular file, not a directory","Look at the wrapped `%w` cause in the message for the exact OS/parser error"],"exampleFix":"# before (.env)\nMY VAR = hello\n\n# after\nMY_VAR=\"hello\"","handlingStrategy":"try-catch","validationCode":"for _, f := range dotenvPaths {\n    if fi, err := os.Stat(f); err == nil && fi.IsDir() {\n        return fmt.Errorf(\"dotenv path %s is a directory\", f)\n    }\n    if err := checkDotenvSyntax(f); err != nil {\n        return err\n    }\n}","typeGuard":"func isReadableFile(path string) bool {\n    fi, err := os.Stat(path)\n    return err == nil && fi.Mode().IsRegular() && fi.Mode().Perm()&0o400 != 0\n}","tryCatchPattern":"env, err := dotenv.Dotenv(vars, node, workingDir)\nif err != nil {\n    var osErr *fs.PathError\n    if errors.As(err, &osErr) {\n        // handle unreadable/missing dotenv file\n    }\n    return fmt.Errorf(\"loading dotenv: %w\", err)\n}","preventionTips":["Validate .env syntax with dotenv linters in CI","Keep dotenv entries pointing at regular files, not directories","Check file permissions when running in containers/CI","Quote values containing spaces or special characters"],"tags":["dotenv","file-io","env","config"],"backgroundTag":"env-file-read-failed","analyzedSha":"385e5ad92af02877b6d7cf9dcc963b5ed916e70a","analyzedAt":"2026-09-05T09:01:05.226Z","contentChangedAt":"2026-09-05T09:01:05.226Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}