Jguer/yay · error
exclude must be a table
Error message
exclude must be a table
What it means
When the UpgradeSelect callback returns a table, its 'exclude' field must be a table (list of package-name strings); a scalar 'exclude' value produces 'exclude must be a table'. The library throws this to reject malformed hook results rather than guessing the intent.
Solutions
- Wrap the value in a table: exclude = { 'pkg1', 'pkg2' }
- Use an empty table exclude = {} if nothing should be excluded
- Omit the exclude key entirely when not needed
- Verify the variable holding the exclude list is actually a table (type(x) == 'table')
Example fix
-- before
return { exclude = 'linux-kernel' }
-- after
return { exclude = { 'linux-kernel' } } Defensive patterns
Strategy: validation
Validate before calling
local r = myUpgradeSelect(mockEvent) assert(r == nil or r.exclude == nil or type(r.exclude) == 'table', 'exclude must be a table')
Type guard
local function hasListExclude(r) return r == nil or r.exclude == nil or type(r.exclude) == 'table' end
Prevention
- Always pass exclude as a list table, even for one entry
- Use {} for no exclusions instead of omitting via nil in a loop
- Document the expected result shape in your config comments
When it happens
Trigger: Callback returns { exclude = <non-table> } — e.g. exclude = 'linux', exclude = 42, or exclude = true.
Common situations: Passing a single package name as a string instead of a list; Lua config built by string concatenation producing the wrong type; misunderstanding that exclude is a set-like table of names.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- exclude entries must be strings
- skip_menu must be a boolean
- unknown upgrade exclusion
- %s: %w
- callback must return nil or table, got
AI-assisted analysis of Jguer/yay@328f4b4939 (2026-09-07).
Data as JSON: /api/errors/702afdf7a428a1f6.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/settings/lua/autocmd.go:367
return tbl
}
func (e *Engine) parseUpgradeSelectResult(value glua.LValue, validExcludes mapset.Set[string]) (UpgradeSelectResult, error) {
var result UpgradeSelectResult
if value == glua.LNil {
return result, nil
}
tbl, ok := value.(*glua.LTable)
if !ok {
return result, fmt.Errorf("callback must return nil or table, got %s", value.Type())
}
if excludeValue := tbl.RawGetString("exclude"); excludeValue != glua.LNil {
excludeTbl, ok := excludeValue.(*glua.LTable)
if !ok {
return result, fmt.Errorf("exclude must be a table")
}
var parseErr error
excludeTbl.ForEach(func(_ glua.LValue, val glua.LValue) {
if parseErr != nil {
return
}
lname, ok := val.(glua.LString)
if !ok {
parseErr = fmt.Errorf("exclude entries must be strings")
return
}
name := string(lname)
if !validExcludes.Contains(name) {
parseErr = fmt.Errorf("unknown upgrade exclusion %q", name)
returnView on GitHub (pinned to 328f4b4939)