{"record":{"id":"356bbbd7990dc480","repo":"kubernetes/kops","slug":"unable-to-read-template-s-error-s","errorCode":null,"errorMessage":"unable to read template: %s, error: %s","messagePattern":"unable to read template: (.+?), error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/toolbox_template.go","lineNumber":179,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"unable to read snippet: %s, error: %s\", j, err)\n\t\t\t}\n\t\t\tsnippets[path.Base(j)] = string(content)\n\t\t}\n\t}\n\n\tchannel, err := kopsapi.LoadChannel(f.VFSContext(), options.channel)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error loading channel %q: %v\", options.channel, err)\n\t}\n\n\t// @step: render each of the templates, splitting on the documents\n\tr := templater.NewTemplater(channel)\n\tvar documents []string\n\tfor _, x := range templates {\n\t\tcontent, err := os.ReadFile(x)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to read template: %s, error: %s\", x, err)\n\t\t}\n\n\t\trendered, err := r.Render(string(content), context, snippets, options.failOnMissing)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to render template: %s, error: %s\", x, err)\n\t\t}\n\t\t// @check if the content is zero ignore it\n\t\tif len(rendered) <= 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !options.formatYAML {\n\t\t\tdocuments = append(documents, strings.Split(rendered, \"---\\n\")...)\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, x := range strings.Split(rendered, \"---\\n\") {\n\t\t\tvar data map[string]interface{}","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/toolbox_template.go#L161-L197","documentation":"Returned by RunToolBoxTemplate when os.ReadFile fails on a template file that expandFiles already listed. The glob expansion succeeded but the individual template file could not be read — usually a permission problem, the file disappearing between listing and read, or a dangling symlink. The template path and underlying OS error are included in the message.","triggerScenarios":"A template file matched by --template-path glob is unreadable: permissions deny read, file deleted between expandFiles and ReadFile (concurrent build cleanup), broken symlink, or the path points at a special/unreadable file.","commonSituations":"Templates with 0600 modes owned by another user; running as a different user in CI than the file owner; tmpdirs or generated template directories being wiped mid-run; symlinked template repos pointing at missing checkouts.","solutions":["Check permissions on the file named in the error (ls -l) and grant read access","Confirm the file exists and isn't a broken symlink: ls -lL <file>","Ensure no concurrent job deletes/moves files in the templates directory during the run","Run the command as a user with read access to all template files"],"exampleFix":"// before\n-rw------- ./templates/cluster.yaml (owned by ci-user, run as deploy-user)\n\n// after\nchmod a+r ./templates/cluster.yaml","handlingStrategy":"try-catch","validationCode":"matches, _ := filepath.Glob(templateDir)\nfor _, f := range matches {\n    fi, err := os.Stat(f)\n    if err != nil || fi.IsDir() || fi.Mode().Perm()&0o400 == 0 {\n        return fmt.Errorf(\"template %s unreadable\", f)\n    }\n}","typeGuard":null,"tryCatchPattern":"content, err := os.ReadFile(templateFile)\nif err != nil {\n    switch {\n    case errors.Is(err, os.ErrPermission):\n        return fmt.Errorf(\"grant read access to %s\", templateFile)\n    case errors.Is(err, os.ErrNotExist):\n        return fmt.Errorf(\"template %s removed since glob expansion\", templateFile)\n    default:\n        return err\n    }\n}","preventionTips":["Keep template files readable (0644) and owned by the user running kops","Do not mutate template directories concurrently with rendering","Verify symlinks in template repos point to existing checkouts"],"tags":["kops","templates","filesystem","permissions"],"backgroundTag":"file-read-permission-denied","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}