grafana/k6 · error

failed to parse template file %s: %w

Error message

failed to parse template file %s: %w

What it means

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>".

Source

Thrown at internal/cmd/templates/templates.go:92

		return tm.browserTemplate, nil
	}

	// Then check if it's a file path
	if isFilePath(tpl) {
		tplPath, err := filepath.Abs(tpl)
		if err != nil {
			return nil, fmt.Errorf("failed to get absolute path for template %s: %w", tpl, err)
		}

		// Read the template content using the provided filesystem
		content, err := fsext.ReadFile(tm.fs, tplPath)
		if err != nil {
			return nil, fmt.Errorf("failed to read template file %s: %w", tpl, err)
		}

		tmpl, err := template.New(filepath.Base(tplPath)).Parse(string(content))
		if err != nil {
			return nil, fmt.Errorf("failed to parse template file %s: %w", tpl, err)
		}

		return tmpl, nil
	}

	// Check if there's a file with this name in current directory
	exists, err := fsext.Exists(tm.fs, fsext.JoinFilePath(".", tpl))
	if err == nil && exists {
		return nil, fmt.Errorf("invalid template type %q, did you mean ./%s?", tpl, tpl)
	}

	return nil, fmt.Errorf("invalid template type %q", tpl)
}

// isFilePath checks if the given string looks like a file path by detecting path separators
// We assume that built-in template names don't contain path separators
func isFilePath(path string) bool {
	return strings.ContainsRune(path, filepath.Separator) || strings.ContainsRune(path, '/')

View on GitHub (pinned to 93accf6570)

Solutions

  1. Fix the Go template grammar: every action is {{ ... }} and each {{if}}/{{range}} needs a matching {{end}}
  2. Reference built-in fields with the leading dot: {{.ScriptName}}, {{.ProjectID}}
  3. Start from a working built-in template (minimal, protocol, browser) and change one thing at a time
  4. Escape literal '{{' in JS with {{"{{"}} if the output must contain it

Example fix

// before
export default function () { console.log('{{ScriptName}}'); }
// after
export default function () { console.log('{{.ScriptName}}'); }
Defensive patterns

Strategy: validation

Validate before calling

// dryparse.go — verify a k6 template parses before using it: go run dryparse.go tpl.js
package main

import (
	"os"
	"text/template"
)

func main() {
	b, err := os.ReadFile(os.Args[1])
	if err != nil {
		panic(err)
	}
	if _, err := template.New("t").Parse(string(b)); err != nil {
		panic(err)
	}
}

Prevention

When it happens

Trigger: A template containing '{{.ScriptName' (unclosed action), '{{if .X}}' without '{{end}}', or '{{ScriptName}}' (missing dot, invalid in Go template syntax).

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/a558e59be6e18877. Report an issue: GitHub.