Skip to content

[go-fan] Go Module Review: github.com/BurntSushi/toml #374

@github-actions

Description

@github-actions

🐹 Go Fan Report: BurntSushi/toml

Module Overview

The BurntSushi/toml package is Go's most popular TOML parser with 4,885+ stars, providing a reflection-based interface similar to json and xml from the standard library. It implements the TOML 1.1 specification for simple, idiomatic configuration file parsing.

Current Usage in gh-aw-mcpg

The project uses this module for configuration file parsing, specifically in internal/config/config.go:

  • Files: 1 file (internal/config/config.go)
  • Import Count: Single focused import
  • Key APIs Used: toml.DecodeFile(path, &cfg) for TOML → struct mapping

Current Implementation:

if _, err := toml.DecodeFile(path, &cfg); err != nil {
    return nil, fmt.Errorf("failed to decode TOML: %w", err)
}

The module is used correctly but discards metadata that could enable validation and better error messages.

Research Findings

Recent Updates

Latest Version: v1.6.0 (December 18, 2025) - We're using v1.5.0 ⚠️

What's New in v1.6.0

  1. TOML 1.1 enabled by default - More lenient parsing (newlines in inline tables, trailing commas)
  2. Duplicate array key detection - Better error messages
  3. Large float encoding fixes - Correct round-tripping for scientific notation
  4. Improved error handling - Better position tracking

Best Practices from Maintainers

  1. Capture metadata - Use the Meta return value for validation
  2. Use struct tags - Explicit toml: tags for all fields
  3. Check undecoded keys - Detect typos with Meta.Undecoded()
  4. Preserve error context - Include line/column numbers from ParseError
  5. Export private fields - Only exported struct fields are decoded

Improvement Opportunities

🏃 Quick Wins (High Impact, Low Effort)

1. Upgrade to v1.6.0 for TOML 1.1 Support

Current: v1.5.0
Action: go get github.com/BurntSushi/toml@v1.6.0

Benefits:

  • TOML 1.1 by default (trailing commas, newlines in inline tables)
  • Better duplicate key detection
  • Scientific notation round-tripping fixes
  • Latest bug fixes and improvements

Impact: More flexible configuration files, better error messages

2. Capture and Use Metadata for Validation

Current: Metadata discarded with _
Recommended:

meta, err := toml.DecodeFile(path, &cfg)
if err != nil {
    return nil, fmt.Errorf("failed to decode TOML: %w", err)
}
// Validate: check for typos, unknown keys
if len(meta.Undecoded()) > 0 {
    log.Printf("Warning: unknown config keys: %v", meta.Undecoded())
}

Benefits:

  • Catch typos in config files (servrrs vs servers)
  • Validate required vs optional fields
  • Better user feedback

Files: internal/config/config.go:80

3. Improve Error Context with Line Numbers

Current: Generic "failed to decode TOML" error
Recommended:

if _, err := toml.DecodeFile(path, &cfg); err != nil {
    if pErr, ok := err.(toml.ParseError); ok {
        return nil, fmt.Errorf("TOML parse error at line %d: %w", pErr.Line, err)
    }
    return nil, fmt.Errorf("failed to decode TOML: %w", err)
}

Benefits: Users get exact line numbers for syntax errors

✨ Feature Opportunities (Medium Impact, Medium Effort)

4. Add Strict Mode for Typo Detection

Use Meta.Undecoded() to detect unknown configuration keys:

if len(meta.Undecoded()) > 0 {
    return nil, fmt.Errorf("unknown config keys: %v", meta.Undecoded())
}

Benefit: Fail fast on configuration typos

5. Add TOML Export Capability

Currently the project only reads TOML. Add marshaling for:

  • Config file generation
  • Config template creation
  • Runtime config dumps
func SaveToFile(cfg *Config, path string) error {
    f, err := os.Create(path)
    if err != nil {
        return err
    }
    defer f.Close()
    return toml.NewEncoder(f).Encode(cfg)
}

📐 Best Practice Alignment

6. Add Explicit Struct Tags

Current: Relies on automatic case matching
Recommended: Explicit toml: tags for all fields

Why: Prevents breaking changes from field name refactoring

Example:

type GatewayConfig struct {
    Port           int    `toml:"port"`
    APIKey         string `toml:"api_key"`
    Domain         string `toml:"domain"`
    StartupTimeout int    `toml:"startup_timeout"`
    ToolTimeout    int    `toml:"tool_timeout"`
}

Files to update: internal/config/config.go (Config, GatewayConfig, ServerConfig)

7. Create Comprehensive Config Example

Current: Config structure only in Go code
Recommended: Create config.example.toml with:

  • All available fields documented
  • Comments explaining each option
  • Example values
  • Required vs optional markers

🔧 General Improvements

8. Add Post-Decode Validation

func (c *Config) Validate(meta toml.MetaData) error {
    if !meta.IsDefined("servers") {
        return errors.New("servers configuration required")
    }
    for name, srv := range c.Servers {
        if srv.Type == "" {
            return fmt.Errorf("server %q missing type field", name)
        }
    }
    return nil
}

Benefit: Fail-fast with clear error messages

Recommendations

Priority 1: Do Now ⚡

  1. Upgrade to v1.6.0 - 5 minutes, significant benefits
  2. Capture metadata - 10 minutes, enables validation
  3. Better error context - 10 minutes, improves debugging

Priority 2: Do Soon 📅

  1. 📝 Add struct tags - 30 minutes, prevents future issues
  2. 🔍 Add strict mode - 15 minutes, catches config typos
  3. 📖 Create config.example.toml - 30 minutes, improves docs

Priority 3: Consider Later 🤔

  1. 💾 Add export capability - If config generation needed
  2. 🔬 Monitor TOML v2 - Code-gen version in development

Next Steps

  1. Update go.mod: go get github.com/BurntSushi/toml@v1.6.0
  2. Modify LoadFromFile() to capture and use metadata
  3. Add toml: tags to all config structs
  4. Create config.example.toml with comprehensive documentation

Module Summary Saved: Analysis details saved to cache for future reference
Review Date: 2026-01-20
Latest Module Version: v1.6.0
Current Version in Use: v1.5.0

References

AI generated by Go Fan

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions