{"record":{"id":"7e901258015b33ed","repo":"Jguer/yay","slug":"s-w-7e9012","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/settings/lua/autocmd.go","lineNumber":228,"sourceCode":"func (e *Engine) RunUpgradeSelect(event *UpgradeSelectEvent) (UpgradeSelectResult, error) {\n\tvar result UpgradeSelectResult\n\tif !e.HasAutocmd(EventUpgradeSelect) {\n\t\treturn result, nil\n\t}\n\n\tvalidExcludes := mapset.NewThreadUnsafeSetWithSize[string](len(event.Upgrades))\n\tfor i := range event.Upgrades {\n\t\tvalidExcludes.Add(event.Upgrades[i].Name)\n\t}\n\n\tseenExcludes := mapset.NewThreadUnsafeSet[string]()\n\tfor _, autocmd := range e.autocmds[EventUpgradeSelect] {\n\t\tif err := e.L.CallByParam(glua.P{\n\t\t\tFn:      autocmd.callback,\n\t\t\tNRet:    1,\n\t\t\tProtect: true,\n\t\t}, e.upgradeSelectTable(event)); err != nil {\n\t\t\treturn result, fmt.Errorf(\"%s: %w\", EventUpgradeSelect, wrapLuaErr(err))\n\t\t}\n\n\t\tvalue := e.L.Get(-1)\n\t\te.L.Pop(1)\n\n\t\thookResult, err := e.parseUpgradeSelectResult(value, validExcludes)\n\t\tif err != nil {\n\t\t\treturn result, fmt.Errorf(\"%s: %w\", EventUpgradeSelect, err)\n\t\t}\n\n\t\tfor _, name := range hookResult.Exclude {\n\t\t\tif !seenExcludes.Add(name) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresult.Exclude = append(result.Exclude, name)\n\t\t}\n\n\t\tif hookResult.SkipMenu {","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/Jguer/yay/blob/328f4b4939fb35f38c2f7c7ce3b8638a839bafa5/pkg/settings/lua/autocmd.go#L210-L246","documentation":"RunUpgradeSelect calls registered 'UpgradeSelect' autocmd callbacks expecting 1 return value; if the Lua call itself fails (script error, abort), the result is wrapped as 'UpgradeSelect: <lua error>'. This means yay could not obtain a valid upgrade-selection decision from the user script. wrapLuaErr strips gopher-lua internals from the message.","triggerScenarios":"An UpgradeSelect autocmd callback raises a Lua error during its protected call (CallByParam with NRet=1) before a return value can be parsed — e.g. calling a nil function, indexing a nil event field, or calling abort().","commonSituations":"User config with a buggy UpgradeSelect hook; script assumes fields on the event table that don't exist in the installed yay version; Lua stdlib function misuse (string.format with wrong args).","solutions":["Read the wrapped Lua error for the failing script line and fix it","Guard against nil fields in the event table inside the callback","Ensure the callback always returns nil or a table as its final statement","Test the callback in a standalone Lua interpreter with a mock event table","Remove/neutralize the autocmd to proceed without script-driven selection"],"exampleFix":"-- before\nautocmd('UpgradeSelect', function(e) return { exclude = filter(e.packages) } end)\n-- after\nautocmd('UpgradeSelect', function(e)\n  if not e or not e.packages then return nil end\n  return { exclude = filter(e.packages) }\nend)","handlingStrategy":"try-catch","validationCode":"-- verify the callback returns a table or nil\nlocal ok, res = pcall(myUpgradeSelect, mockEvent)\nif not ok then error('hook errors: ' .. tostring(res)) end\nassert(res == nil or type(res) == 'table', 'must return nil or table')","typeGuard":null,"tryCatchPattern":"result, err := engine.RunUpgradeSelect(event, validExcludes)\nif err != nil {\n\tlog.Warnf(\"UpgradeSelect hook failed (%v); using default selection\", err)\n\tresult = defaultSelection\n}","preventionTips":["Always end every code path of the callback with `return nil` or a table","Wrap the callback body in pcall and return nil on failure","Test the hook against a mock event before enabling it"],"tags":["lua","autocmd","upgrade","callback"],"backgroundTag":"script-callback-runtime-error","analyzedSha":"328f4b4939fb35f38c2f7c7ce3b8638a839bafa5","analyzedAt":"2026-09-07T16:45:12.608Z","contentChangedAt":"2026-09-07T16:45:12.608Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}