{"record":{"id":"b0760255860ac753","repo":"Jguer/yay","slug":"entry-keys-must-be-strings-got-s","errorCode":null,"errorMessage":"entry keys must be strings, got %s","messagePattern":"entry keys must be strings, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/settings/lua/lua.go","lineNumber":233,"sourceCode":"\n\ttype namedElem struct {\n\t\tname string\n\t\telem reflect.Value\n\t}\n\n\tvar (\n\t\tentries  []namedElem\n\t\tfirstErr error\n\t)\n\n\ttbl.ForEach(func(k, entry lua.LValue) {\n\t\tif firstErr != nil {\n\t\t\treturn\n\t\t}\n\n\t\tname, ok := k.(lua.LString)\n\t\tif !ok {\n\t\t\tfirstErr = fmt.Errorf(\"entry keys must be strings, got %s\", k.Type())\n\t\t\treturn\n\t\t}\n\n\t\tentryTbl, ok := entry.(*lua.LTable)\n\t\tif !ok {\n\t\t\tfirstErr = fmt.Errorf(\"entry %q must be a table, got %s\", string(name), entry.Type())\n\t\t\treturn\n\t\t}\n\n\t\telem := reflect.New(elemType).Elem()\n\t\tif hasName {\n\t\t\telem.Field(nameIdx).SetString(string(name))\n\t\t}\n\n\t\tif err := assignStructFields(elem, entryTbl, fieldIndex); err != nil {\n\t\t\tfirstErr = fmt.Errorf(\"entry %q: %w\", string(name), err)\n\t\t\treturn\n\t\t}","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/Jguer/yay/blob/328f4b4939fb35f38c2f7c7ce3b8638a839bafa5/pkg/settings/lua/lua.go#L215-L251","documentation":"assignStructSlice iterates the outer yay.opt table and requires each key to be an LString, because the key becomes the entry's name stored in the struct's lua:\"name\" field. Numeric array-style keys or other key types abort with 'entry keys must be strings, got <type>'.","triggerScenarios":"Using an array-style (1-based) list in init.lua for a struct-slice option, e.g. yay.opt.ignored = {\"pkg1\",\"pkg2\"}, or mixing numeric keys into the name-keyed table.","commonSituations":"Writing {\"a\",\"b\"} out of list habit instead of a map keyed by entry name; building the table programmatically with table.insert, which produces numeric keys.","solutions":["Rewrite the value as a name-keyed map: yay.opt.ignored = { pkg1 = {}, pkg2 = {} }","If building in Lua, index by explicit string names instead of table.insert","Ensure no bare numeric keys are mixed into the entry table"],"exampleFix":"// before (init.lua)\nyay.opt.ignored = { \"linux-headers\" }\n// after\nyay.opt.ignored = { [\"linux-headers\"] = {} }","handlingStrategy":"validation","validationCode":"-- init.lua\nfor k in pairs(yay.opt.ignored or {}) do\n    assert(type(k) == \"string\", \"ignored entries must be keyed by package name strings\")\nend","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"entry keys must be strings\") {\n    convertListToNameKeyedTableInInitLua()\n}","preventionTips":["Use name-keyed maps { name = {...} }, not arrays { ... }","Avoid table.insert when building option tables; assign by string key","Add a Lua-side loop asserting all keys are strings before handing options to yay.opt"],"tags":["lua","type-mismatch","configuration"],"backgroundTag":"type-mismatch","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"}