Problem
config.Load throws away the decoder metadata:
// internal/config/config.go
if _, err := toml.DecodeFile(path, cfg); err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", path, err)
}
toml.DecodeFile returns a MetaData whose Undecoded() method lists every key present in the file that did not map to a struct field. Discarding it means a misspelled or misplaced key is silently ignored — the file parses fine and the server starts with a default the operator did not choose.
This fails in a genuinely confusing way. Write api_ke instead of api_key under [cartesia] and you get [cartesia] api_key missing at startup while staring at a config file that visibly contains an api key. Put barge_in at the top level instead of under [pipeline] and barge-in silently stays at its default with no complaint at all. Config here is the entire operator interface — nearly every knob (provider selection, endpointing, barge-in timing, TURN credentials) is a TOML key, so a typo class that fails silently is expensive.
Proposed change
Capture the metadata and report unknown keys.
md, err := toml.DecodeFile(path, cfg)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", path, err)
}
if undecoded := md.Undecoded(); len(undecoded) > 0 {
// join keys with ", " and surface them
}
Warn or fail? Suggest warning by default via log.Printf — hard-failing could break a running deployment on upgrade if someone is carrying a key we later remove. A follow-up could add --strict-config to turn it into an error. Open to the opposite call from a maintainer; say so on the issue before starting if you prefer a hard error.
One wrinkle worth handling: keys under [plugins] and any provider section the build doesn't know about should still be reported, but the message should read as advice ("unknown key ... — check for a typo"), not as an error.
Acceptance criteria
Pointers
internal/config/config.go — Load(), ~L286
github.com/BurntSushi/toml — MetaData.Undecoded() returns []Key; Key.String() gives the dotted path
Problem
config.Loadthrows away the decoder metadata:toml.DecodeFilereturns aMetaDatawhoseUndecoded()method lists every key present in the file that did not map to a struct field. Discarding it means a misspelled or misplaced key is silently ignored — the file parses fine and the server starts with a default the operator did not choose.This fails in a genuinely confusing way. Write
api_keinstead ofapi_keyunder[cartesia]and you get[cartesia] api_keymissing at startup while staring at a config file that visibly contains an api key. Putbarge_inat the top level instead of under[pipeline]and barge-in silently stays at its default with no complaint at all. Config here is the entire operator interface — nearly every knob (provider selection, endpointing, barge-in timing, TURN credentials) is a TOML key, so a typo class that fails silently is expensive.Proposed change
Capture the metadata and report unknown keys.
Warn or fail? Suggest warning by default via
log.Printf— hard-failing could break a running deployment on upgrade if someone is carrying a key we later remove. A follow-up could add--strict-configto turn it into an error. Open to the opposite call from a maintainer; say so on the issue before starting if you prefer a hard error.One wrinkle worth handling: keys under
[plugins]and any provider section the build doesn't know about should still be reported, but the message should read as advice ("unknown key ... — check for a typo"), not as an error.Acceptance criteria
api_ke = "x"under a provider section produces a message namingcartesia.api_ke.internal/config/config_test.gothat writes a temp TOML file with a bogus key and asserts the key is reported.Pointers
internal/config/config.go—Load(), ~L286github.com/BurntSushi/toml—MetaData.Undecoded()returns[]Key;Key.String()gives the dotted path