{"record":{"id":"a558e59be6e18877","repo":"grafana/k6","slug":"failed-to-parse-template-file-s-w","errorCode":null,"errorMessage":"failed to parse template file %s: %w","messagePattern":"failed to parse template file (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/templates/templates.go","lineNumber":92,"sourceCode":"\t\treturn tm.browserTemplate, nil\n\t}\n\n\t// Then check if it's a file path\n\tif isFilePath(tpl) {\n\t\ttplPath, err := filepath.Abs(tpl)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get absolute path for template %s: %w\", tpl, err)\n\t\t}\n\n\t\t// Read the template content using the provided filesystem\n\t\tcontent, err := fsext.ReadFile(tm.fs, tplPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read template file %s: %w\", tpl, err)\n\t\t}\n\n\t\ttmpl, err := template.New(filepath.Base(tplPath)).Parse(string(content))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse template file %s: %w\", tpl, err)\n\t\t}\n\n\t\treturn tmpl, nil\n\t}\n\n\t// Check if there's a file with this name in current directory\n\texists, err := fsext.Exists(tm.fs, fsext.JoinFilePath(\".\", tpl))\n\tif err == nil && exists {\n\t\treturn nil, fmt.Errorf(\"invalid template type %q, did you mean ./%s?\", tpl, tpl)\n\t}\n\n\treturn nil, fmt.Errorf(\"invalid template type %q\", tpl)\n}\n\n// isFilePath checks if the given string looks like a file path by detecting path separators\n// We assume that built-in template names don't contain path separators\nfunc isFilePath(path string) bool {\n\treturn strings.ContainsRune(path, filepath.Separator) || strings.ContainsRune(path, '/')","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cmd/templates/templates.go#L74-L110","documentation":"The template file was read successfully but its content is not valid Go text/template syntax (template.New(...).Parse failed). k6 templates use Go template actions with fields like {{.ScriptName}} and {{.ProjectID}}; malformed actions (unclosed {{, missing {{end}}) or JS-style placeholders without the leading dot produce a parse error wrapped as \"failed to parse template file <tpl>\".","triggerScenarios":"A template containing '{{.ScriptName' (unclosed action), '{{if .X}}' without '{{end}}', or '{{ScriptName}}' (missing dot, invalid in Go template syntax).","commonSituations":"Converting Mustache/Handlebars JS templates to k6's Go-template format; hand-editing generated templates and breaking delimiters; brace-heavy JS code accidentally containing {{ sequences.","solutions":["Fix the Go template grammar: every action is {{ ... }} and each {{if}}/{{range}} needs a matching {{end}}","Reference built-in fields with the leading dot: {{.ScriptName}}, {{.ProjectID}}","Start from a working built-in template (minimal, protocol, browser) and change one thing at a time","Escape literal '{{' in JS with {{\"{{\"}} if the output must contain it"],"exampleFix":"// before\nexport default function () { console.log('{{ScriptName}}'); }\n// after\nexport default function () { console.log('{{.ScriptName}}'); }","handlingStrategy":"validation","validationCode":"// dryparse.go — verify a k6 template parses before using it: go run dryparse.go tpl.js\npackage main\n\nimport (\n\t\"os\"\n\t\"text/template\"\n)\n\nfunc main() {\n\tb, err := os.ReadFile(os.Args[1])\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif _, err := template.New(\"t\").Parse(string(b)); err != nil {\n\t\tpanic(err)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start from built-in templates and edit incrementally","Always use the leading dot for fields: {{.ScriptName}}, {{.ProjectID}}","Close every {{if}}/{{range}} with {{end}}","Add a text/template parse step to CI for custom templates"],"tags":["cli","templates","go-template","parsing"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}