Fix Go Template Error: "can't evaluate field Username in type main.User"

beginner🔷 Go2026-06-18| Go 1.18+, Linux/macOS/Windows, html/template or text/template packages

Error Message

template: mytemplate:5:8: executing "mytemplate" at <.Username>: can't evaluate field Username in type main.User
#template#html/template#struct#reflection

The Error MessageYou refresh your Go web application, expecting a personalized dashboard, but find a 500 error instead. Checking the logs reveals this specific failure:

template: mytemplate:5:8: executing "mytemplate" at : can't evaluate field Username in type main.User

This happens because the template engine tried to access a piece of data it couldn't see. Usually, the culprit is a private field or a misunderstanding of how the "dot" context shifts during execution.

Root Cause: Exported vs. Unexported FieldsVisibility rules in Go are simple: uppercase is public (exported), lowercase is private (unexported). The html/template package uses reflection to read your structs at runtime. However, reflection cannot bypass Go's security to access private fields.

Imagine your struct looks like this:

type User struct {
    username string // Private
    Email    string // Public
}

Even if you pass the data correctly, {{.username}} will fail. The engine treats private fields as if they don't exist.

Fixing the Error### 1. Capitalize Your Struct FieldsThe quickest fix involves changing your struct definition. Ensure every field used in a template starts with an uppercase letter.

type User struct {
    Username string
    Email    string
}

Update your template to match: <p>Hello, {{.Username}}!</p>. This simple change resolves 90% of these errors.

2. Master the "Dot" ContextThe "dot" (.) represents your current cursor. It changes when you enter a {{range}} or {{with}} block. If you iterate through a list of blog posts, the dot is no longer your top-level data; it becomes the specific post you're currently processing.

{{range .Posts}}
    <p>Posted by: {{.User.Username}}</p> <!-- This often fails! -->
{{end}}

If User is a property of your global data and not the Post struct, the template will crash. Use $ to jump back to the original data root passed to the template:

{{range .Posts}}
    <li>Written by: {{$.User.Username}}</li> <!-- This works! -->
{{end}}

3. Check Case SensitivityGo is unforgiving with casing. If your struct defines Username but your HTML template calls {{.UserName}} (note the capital 'N'), the evaluation fails immediately. Go templates do not provide "fuzzy matching" for field names.

Verify the FixDon't restart your entire server just to test a small fix. Use a quick standalone script to confirm the template parses and executes correctly.

package main

import (
    "html/template"
    "os"
)

type User struct {
    Username string
}

func main() {
    const doc = `<p>Hello, {{.Username}}!</p>`
    t := template.Must(template.New("test").Parse(doc))
    
    // Test with real data
    err := t.Execute(os.Stdout, User{Username: "Alice"})
    if err != nil {
        panic(err)
    }
}

Prevention Tips- Run go vet: This built-in tool catches many template syntax errors before you even run the code.- Avoid generic maps: Passing map[string]any is tempting but dangerous. Strongly typed structs provide better IDE support and help you catch typos during development.- Standardize naming: If your JSON uses user_name, your struct uses Username, and your template uses UserName, you're asking for trouble. Keep your names consistent across all layers.

Related Error Notes