-
Notifications
You must be signed in to change notification settings - Fork 14
Description
πΉ Go Fan Report: BurntSushi/toml
Daily Go module review β round-robin cycle, prioritizing recently updated dependencies
Module Overview
github.com/BurntSushi/toml is the canonical TOML parser and encoder for Go. It uses reflection for struct marshaling/unmarshaling, implements the full TOML 1.1 spec, and provides rich parse error reporting with source context (line snippet + column pointer). The project is on v1.6.0 β the latest release (2025-12-18). β
Current Usage in gh-aw-mcpg
- Files: 1 file (
internal/config/config_core.go) - Import Count: 1 import
- Key APIs Used:
toml.NewDecoder(file)β streaming decoderdecoder.Decode(&cfg)β returnsMetaDatamd.Undecoded()β unknown field detection (warns instead of hard errors)toml.ParseErrorβ error with.Position.Line,.Position.Col,.Message
The TOML module is used exclusively for loading gateway configuration from .toml files. Usage is focused, purposeful, and already on the latest version.
Research Findings
Recent Updates (v1.6.0 β 2025-12-18)
- TOML 1.1 spec enabled by default: Multi-line inline arrays and improved newline handling are now on by default (previously opt-in via
BURNTSUSHI_TOML_110env var) - Duplicate key detection fixed:
arr = [1]; arr = [2]now correctly returns a parse error - Large float encoding fixed:
5e+22round-trips correctly using exponent syntax
Best Practices from the Library
ParseError.Error()is the canonical error display method β it returns the full formatted error including the problematic TOML source line and a^pointer to the exact column. It's designed for end-user display.ParseError.Messageis for programmatic inspection only β it's the short description without source context.toml.Marshal(v)(added v1.4.0) is the idiomatic way to encode Go structs to TOML.
Improvement Opportunities
π Quick Wins
1. Remove dead-code pointer assertion for *toml.ParseError (config_core.go:220)
The library's Decode method returns toml.ParseError as a value type (not a pointer). The pointer type assertion err.(*toml.ParseError) will never match and is dead code. Removing it simplifies error handling.
Current code:
if perr, ok := err.(*toml.ParseError); ok { // β Dead code: never matches
return nil, fmt.Errorf("failed to parse TOML at line %d, column %d: %s",
perr.Position.Line, perr.Position.Col, perr.Message)
}
// Try value type (used by toml.Decode)
if perr, ok := err.(toml.ParseError); ok {
return nil, fmt.Errorf("failed to parse TOML at line %d, column %d: %s",
perr.Position.Line, perr.Position.Col, perr.Message)
}Simplified:
if perr, ok := err.(toml.ParseError); ok {
return nil, fmt.Errorf("failed to parse TOML at line %d, column %d: %s",
perr.Position.Line, perr.Position.Col, perr.Message)
}
```
#### 2. Use `perr.Error()` for richer config error messages
The library's `ParseError.Error()` returns a beautifully formatted multi-line message that includes the TOML source snippet and a `^` arrow pointing exactly to the error column β dramatically better UX for users debugging mistyped config files. The current code discards this context and manually formats a simpler message using just `perr.Message`.
**Current:**
```
failed to parse TOML at line 5, column 12: expected value but found 'x'
```
**With `perr.Error()` (library's designed output):**
```
failed to parse config.toml:
5 | port = x
^
Error: expected value but found 'x'Suggested change:
if perr, ok := err.(toml.ParseError); ok {
return nil, fmt.Errorf("failed to parse TOML: %w", perr)
}The %w wrapping preserves the structured error for callers that want to inspect it programmatically, while perr.Error() surfaces the full context for display.
β¨ Feature Opportunities
-
toml.Marshalin test helpers: Config tests use raw TOML strings (e.g., inconfig_test.go). Usingtoml.Marshal(cfg)to generate test TOML from Go structs would be compile-time type-checked, prevent TOML syntax typos in test data, and be more maintainable as theConfigstruct evolves.// Instead of raw strings: tomlStr := `[gateway]\nport = 3000\n` // Use marshal: tomlBytes, err := toml.Marshal(struct { Gateway GatewayConfig `toml:"gateway"` }{Gateway: GatewayConfig{Port: 3000}})
-
toml.Unmarshalfor in-memory test configs: For small in-memory config construction in tests,toml.Unmarshal([]byte(s), &cfg)is simpler than creating a decoder from astrings.Reader.
π Best Practice Alignment
- Error wrapping with
%w: The current error formatting loses the structuredParseErrortype for downstream handlers (callers can't useerrors.Asto inspect parse position). Usingfmt.Errorf("failed to parse TOML: %w", perr)preserves the full error chain.
π§ General Improvements
- The
logConfigvariable (config_core.go:282) still uses the oldlog.New(io.Discard, "[CONFIG] ", log.LstdFlags)+SetDebug()pattern, while the rest of the config package useslogger.New("config:config")from the internal logger. While not directly a TOML usage issue, consolidating to the project's logger convention would be cleaner.
Recommendations
| Priority | Action | Impact |
|---|---|---|
| High | Use perr.Error() (or %w wrapping) instead of manually formatting perr.Message |
Better user experience when configs have syntax errors |
| Medium | Remove dead *toml.ParseError pointer assertion |
Code clarity, removes misleading comment |
| Low | Use toml.Marshal in test helpers |
Test maintainability |
Next Steps
- Remove dead
*toml.ParseErrorpointer type assertion inLoadFromFile - Improve parse error messages to use
perr.Error()orfmt.Errorf("...: %w", perr)for full context - (Optional) Use
toml.Marshalin config package tests for struct-based test fixtures
Generated by Go Fan πΉ
Module summary saved to: specs/mods/toml.md (session artifact)
Run: Β§22991041517
- expires on Mar 19, 2026, 7:34 AM UTC