{"record":{"id":"46672e22130f898f","repo":"Billionmail/BillionMail","slug":"failed-to-read-html-template-w","errorCode":null,"errorMessage":"failed to read HTML template: %w","messagePattern":"failed to read HTML template: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/controller/subscribe_list/subscribe_list.go","lineNumber":109,"sourceCode":"// Update contact status: confirm (0,1), subscribe = 1\nfunc updateContactStatus(email string, groupId int, status int) error {\n\t_, err := g.DB().Model(\"bm_contacts\").\n\t\tData(g.Map{\"status\": status, \"active\": 1}).\n\t\tWhere(\"email\", email).\n\t\tWhere(\"group_id\", groupId).\n\t\tUpdate()\n\n\treturn err\n}\n\nfunc readTemplateFiles(baseFilename string) (htmlContent string, txtContent string, err error) {\n\thtmlPath := filepath.Join(public.AbsPath(\"../core/template\"), baseFilename+\".html\")\n\ttxtPath := filepath.Join(public.AbsPath(\"../core/template\"), baseFilename+\".txt\")\n\n\t// Read HTML file\n\thtmlBytes, err := os.ReadFile(htmlPath)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to read HTML template: %w\", err)\n\t}\n\n\t// Read TXT file (allowed to not exist)\n\ttxtBytes, err := os.ReadFile(txtPath)\n\tif err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\tg.Log().Debugf(context.Background(),\n\t\t\t\t\"failed to read TXT template: %v, path: %s\", err, txtPath)\n\t\t}\n\t\ttxtBytes = []byte(\"\") // Return empty content if file does not exist\n\t}\n\n\treturn string(htmlBytes), string(txtBytes), nil\n}\n\nfunc GetDefaultTemplate(emailType int) (html string, txt string) {\n\tvar (\n\t\tdefaultHtml string","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/subscribe_list/subscribe_list.go#L91-L127","documentation":"readTemplateFiles loads the default subscribe-page HTML template from core/template/<baseFilename>.html; if os.ReadFile fails (missing file, wrong working directory, permissions) the error is wrapped with %w so the underlying os error (e.g. 'no such file or directory') is preserved.","triggerScenarios":"GetDefaultTemplate called while the HTML template file is absent from core/template, the template directory was not deployed (Docker image/volume missing), or AbsPath resolves to the wrong location because the binary's working directory changed.","commonSituations":"Deploying only the binary without the template/ directory; custom baseFilename that doesn't exist; container volume mounted over core/template; running tests from a directory where '../core/template' doesn't resolve.","solutions":["Verify core/template/<baseFilename>.html exists on the deployed host and is readable by the process user.","Redeploy including the template/ directory (or fix the Docker image/COPY step).","Log/inspect public.AbsPath(\"../core/template\") output and fix path resolution if the binary runs from an unexpected cwd.","Restore correct file permissions if the file exists but is unreadable."],"exampleFix":"// before\nhtmlPath := filepath.Join(public.AbsPath(\"../core/template\"), baseFilename+\".html\")\n// after\nbase := public.AbsPath(\"../core/template\")\nif _, err := os.Stat(base); err != nil {\n    return \"\", \"\", fmt.Errorf(\"template dir missing at %s\", base)\n}\nhtmlPath := filepath.Join(base, baseFilename+\".html\")","handlingStrategy":"fallback","validationCode":"const htmlPath = path.join(templateDir, baseFilename + '.html')\nif (!fs.existsSync(htmlPath)) {\n  throw new Error(`Deployed package missing template: ${htmlPath}`)\n}","typeGuard":null,"tryCatchPattern":"html, txt, err := readTemplateFiles(baseFilename)\nif err != nil {\n  log.Printf(\"template load failed: %v\", err) // wrapped os error shows real path/problem\n  return defaultEmbeddedTemplate // fallback to embedded template asset\n}","preventionTips":["Ship the template/ directory in the Docker image/deployment artifact","Use go:embed for templates so they cannot be missing at runtime","Log public.AbsPath resolution when the process cwd may vary","Add a startup health check that stats the template directory"],"tags":["filesystem","template","deployment"],"backgroundTag":"template-file-not-found","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}