Commit a7b390d
authored
Improve TOML configuration error handling with position tracking and typo detection (#813)
Configuration parse errors lacked position context and silently ignored
typos in field names, leading to debugging friction and silent
misconfigurations.
## Changes
### Precise error locations
Extract line and column from `ParseError.Position` for pinpoint
debugging:
```go
// Before
Error: failed to parse TOML: toml: line 2 (last key "gateway"): expected '.' or '='...
// After
Error: failed to parse TOML at line 2, column 6: expected '.' or '=', but got '3' instead
```
### Unknown key detection
Use `MetaData.Undecoded()` to catch typos and deprecated fields:
```toml
[gateway]
prot = 3000 # Typo detected
startup_timout = 30 # Typo detected
```
Generates warnings:
```
[WARN] [config] Unknown configuration key 'gateway.prot' - check for typos
[WARN] [config] Unknown configuration key 'gateway.startup_timout' - check for typos
```
### Streaming decoder
Replace `os.ReadFile` + `toml.Decode` with `toml.NewDecoder` for memory
efficiency with large config files.
### Test coverage
- Parse errors with column numbers
- Unknown key detection in gateway and server sections
- Multiple simultaneous typos
- Large file handling (100+ servers)
- TOML 1.1 duplicate key detection
### Documentation
Added "Configuration Validation and Error Handling" section to README
with examples and best practices.
> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `example.com`
> - Triggering command: `/tmp/go-build4210791917/b271/launcher.test
/tmp/go-build4210791917/b271/launcher.test
-test.testlogfile=/tmp/go-build4210791917/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net -trimpath
64/pkg/tool/linux_amd64/vet -p github.com/davec--norc -lang=go1.16
64/pkg/tool/linux_amd64/vet -I 519236/b216/_pkg_.a cfg fig.test
--gdwarf-5 b/gh-aw-mcpg/intdocker-cli-plugin-metadata -o fig.test` (dns
block)
> - Triggering command: `/tmp/go-build3777671178/b275/launcher.test
/tmp/go-build3777671178/b275/launcher.test
-test.testlogfile=/tmp/go-build3777671178/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true t n for TOML
configuration validation and error handling
Co-autho--format=format:%H %ct %D
ache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
ache/go/1.25.6/x/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/compile
-I` (dns block)
> - `invalid-host-that-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build3314539425/b001/config.test
/tmp/go-build3314539425/b001/config.test
-test.testlogfile=/tmp/go-build3314539425/b001/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true go k1BRF76vb
x_amd64/vet
credential.helpe/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/compile`
(dns block)
> - Triggering command: `/tmp/go-build4210791917/b259/config.test
/tmp/go-build4210791917/b259/config.test
-test.testlogfile=/tmp/go-build4210791917/b259/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net
ache/go/1.25.6/x64/src/go/scanner/errors.go bin/as -I /tmp/go-build962-o
-I 1.o -o 64/src/net -trimpath 64/pkg/tool/linu-lang=go1.25 -p
crypto/sha256 -lang=go1.25 64/pkg/tool/linu-goversion` (dns block)
> - Triggering command: `/tmp/go-build3777671178/b263/config.test
/tmp/go-build3777671178/b263/config.test
-test.testlogfile=/tmp/go-build3777671178/b263/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true .cfg
by/8ae1b12e94aa80f9eaed17e6ee8f6f9b1e1c0807ed03bea0920b88cdb129e6eb
64/pkg/tool/linux_amd64/vet by/8ae1b12e94aa8git
920b88cdb129e6ebrev-parse rgo/bin/as 64/pkg/tool/linux_amd64/vet dock��
-o n for TOML configuration validation and error handling
Co-autho-buildid=HBV11mEKIlvfULJyOluM/u0/tmp/go-build673569813/b262/vet.cfg
ache/go/1.25.6/x64/pkg/tool/linux_amd64/vet ache/go/1.25.6/xbash -I
ache/go/1.25.6/x--noprofile ache/go/1.25.6/x64/pkg/tool/linux_amd64/vet`
(dns block)
> - `nonexistent.local`
> - Triggering command: `/tmp/go-build4210791917/b271/launcher.test
/tmp/go-build4210791917/b271/launcher.test
-test.testlogfile=/tmp/go-build4210791917/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net -trimpath
64/pkg/tool/linux_amd64/vet -p github.com/davec--norc -lang=go1.16
64/pkg/tool/linux_amd64/vet -I 519236/b216/_pkg_.a cfg fig.test
--gdwarf-5 b/gh-aw-mcpg/intdocker-cli-plugin-metadata -o fig.test` (dns
block)
> - Triggering command: `/tmp/go-build3777671178/b275/launcher.test
/tmp/go-build3777671178/b275/launcher.test
-test.testlogfile=/tmp/go-build3777671178/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true t n for TOML
configuration validation and error handling
Co-autho--format=format:%H %ct %D
ache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
ache/go/1.25.6/x/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/compile
-I` (dns block)
> - `slow.example.com`
> - Triggering command: `/tmp/go-build4210791917/b271/launcher.test
/tmp/go-build4210791917/b271/launcher.test
-test.testlogfile=/tmp/go-build4210791917/b271/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net -trimpath
64/pkg/tool/linux_amd64/vet -p github.com/davec--norc -lang=go1.16
64/pkg/tool/linux_amd64/vet -I 519236/b216/_pkg_.a cfg fig.test
--gdwarf-5 b/gh-aw-mcpg/intdocker-cli-plugin-metadata -o fig.test` (dns
block)
> - Triggering command: `/tmp/go-build3777671178/b275/launcher.test
/tmp/go-build3777671178/b275/launcher.test
-test.testlogfile=/tmp/go-build3777671178/b275/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true t n for TOML
configuration validation and error handling
Co-autho--format=format:%H %ct %D
ache/go/1.25.6/x64/pkg/tool/linux_amd64/vet
ache/go/1.25.6/x/opt/hostedtoolcache/go/1.25.6/x64/pkg/tool/linux_amd64/compile
-I` (dns block)
> - `this-host-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build4210791917/b280/mcp.test
/tmp/go-build4210791917/b280/mcp.test
-test.testlogfile=/tmp/go-build4210791917/b280/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
/opt/hostedtoolcache/go/1.25.6/x64/src/runtime/cgo 519236/b184/
64/bin/go --gdwarf-5 --64 ut-2370224496.c as 5192��
ache/go/1.25.6/x64/src/net -I cfg --gdwarf-5 --64 -o
RL1q3u8/2td8KcPQCBPBYpO4RxDG` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/github/gh-aw-mcpg/settings/copilot/coding_agent)
(admins only)
>
> </details>
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
----
*This section details on the original issue you should resolve*
<issue_title>[go-fan] Go Module Review: BurntSushi/toml</issue_title>
<issue_description># 🐹 Go Fan Report: github.com/BurntSushi/toml
## Module Overview
BurntSushi/toml is **the** de-facto standard TOML parser for Go with
4,893 stars and active maintenance. This library provides a
reflection-based API for encoding and decoding TOML configuration files,
implementing the TOML specification with excellent compliance. The
project is currently using **v1.6.0** (released December 18, 2025).
## Current Usage in gh-aw-mcpg
The TOML library has a focused, minimal footprint in the gateway:
- **Files**: 1 file (`internal/config/config_core.go`)
- **Import Count**: 1 import
- **Key APIs Used**:
- `toml.Decode()` - Single usage for parsing TOML configuration into Go
structs
**Current implementation** (lines 97-98 of `config_core.go`):
```````go
if _, err := toml.Decode(string(data), &cfg); err != nil {
return nil, fmt.Errorf("failed to parse TOML: %w", err)
}
``````
### Usage Pattern Analysis
✅ **Strengths**: Clean, simple, effective for basic parsing
4 files changed
Lines changed: 234 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
214 | 259 | | |
215 | 260 | | |
216 | 261 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
142 | | - | |
143 | | - | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
144 | 150 | | |
145 | 151 | | |
146 | 152 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
91 | 92 | | |
92 | 93 | | |
93 | 94 | | |
94 | | - | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
95 | 98 | | |
96 | | - | |
| 99 | + | |
97 | 100 | | |
| 101 | + | |
98 | 102 | | |
99 | | - | |
100 | | - | |
| 103 | + | |
101 | 104 | | |
102 | | - | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
103 | 122 | | |
104 | 123 | | |
105 | 124 | | |
106 | 125 | | |
107 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
108 | 137 | | |
109 | 138 | | |
110 | 139 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1096 | 1096 | | |
1097 | 1097 | | |
1098 | 1098 | | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
0 commit comments