grafana/k6 · error

invalid template type %q, did you mean ./%s?

Error message

invalid template type %q, did you mean ./%s?

What it means

The --template value is not a built-in name and contains no path separator (so it is not treated as a file), but a file with exactly that name exists in the current directory. k6 guesses the user forgot the ./ prefix and reports "invalid template type \"<name>\", did you mean ./<name>?" instead of silently picking the local file.

Source

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

		// 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, '/')
}

// TemplateArgs represents arguments passed to templates
type TemplateArgs struct {
	ScriptName string
	ProjectID  string
}

// ExecuteTemplate applies the template with provided arguments and writes to the provided writer

View on GitHub (pinned to 93accf6570)

Solutions

  1. Prefix the file with ./: k6 new --template=./mytpl.js script.js
  2. Or pass an absolute path to the template file
  3. For built-ins, use the exact reserved names (minimal, protocol, browser)

Example fix

# before
k6 new --template=mytpl.js script.js
# after
k6 new --template=./mytpl.js script.js
Defensive patterns

Strategy: validation

Validate before calling

# Normalize local template files to ./ form before invoking k6
tpl=mytpl.js
[ -f "$tpl" ] && tpl="./$tpl"
k6 new --template="$tpl" script.js

Prevention

When it happens

Trigger: Running 'k6 new --template=mytpl.js script.js' while ./mytpl.js exists in the cwd; isFilePath() returns false because the value has no '/' or separator, so it is classified as a template type name and falls through to the local-file hint.

Common situations: Users expecting shell-like path resolution from k6 arguments; copy-pasted commands that omit ./; switching between built-in names and local files.

Related errors


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