{"record":{"id":"9b11c3585b183cd3","repo":"Jguer/yay","slug":"unsupported-slice-element-kind-s","errorCode":null,"errorMessage":"unsupported slice element kind %s","messagePattern":"unsupported slice element kind (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/settings/lua/lua.go","lineNumber":201,"sourceCode":"\tdefault:\n\t\treturn fmt.Errorf(\"unsupported field kind %s\", field.Kind())\n\t}\n\n\treturn nil\n}\n\n// assignStructSlice fills a []Struct field from a Lua table keyed by name, e.g.\n//\n//\t{ [\"core\"] = { url = \"...\" }, [\"extra\"] = { url = \"...\" } }\n//\n// Each entry becomes one struct: the table key populates the element's\n// lua:\"name\" field and the sub-table populates the remaining fields. Entries\n// are sorted by name so the resulting slice is deterministic despite Lua's\n// unordered table iteration.\nfunc assignStructSlice(field reflect.Value, val lua.LValue) error {\n\telemType := field.Type().Elem()\n\tif elemType.Kind() != reflect.Struct {\n\t\treturn fmt.Errorf(\"unsupported slice element kind %s\", elemType.Kind())\n\t}\n\n\ttbl, ok := val.(*lua.LTable)\n\tif !ok {\n\t\treturn fmt.Errorf(\"expected table, got %s\", val.Type())\n\t}\n\n\t// The name comes from the table key, so a \"name\" key inside the entry table\n\t// would silently override it and let two entries share one name. Drop it\n\t// from the assignable set so it is reported as an unknown key instead.\n\tfieldIndex := luaFieldIndex(elemType)\n\tnameIdx, hasName := fieldIndex[\"name\"]\n\tdelete(fieldIndex, \"name\")\n\n\ttype namedElem struct {\n\t\tname string\n\t\telem reflect.Value\n\t}","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/Jguer/yay/blob/328f4b4939fb35f38c2f7c7ce3b8638a839bafa5/pkg/settings/lua/lua.go#L183-L219","documentation":"assignStructSlice implements the Slice case of assign but only supports slices whose element type is a struct ([]Struct with a lua:\"name\" field). Any other element kind ([]string, []int, []any) is rejected, naming the element's reflect.Kind.","triggerScenarios":"A lua-tagged struct field is declared as []string, []int, or another non-struct slice, and init.lua assigns a table to the corresponding yay.opt key; or a refactor changes the element type of an existing slice field.","commonSituations":"Wanting a list of strings (e.g. yay.opt.ignored_pkgs = {\"a\",\"b\"}) and modeling it as []string, which the engine does not support.","solutions":["Change the field to a slice of a named struct with a lua:\"name\" key field (e.g. []Pkg where Pkg has Name string `lua:\"name\"`)","Model key–value string lists as that struct slice, one entry per name","Remove the lua tag from the field if it should not be Lua-configurable"],"exampleFix":"// before\nIgnored []string `lua:\"ignored\"`\n// after\ntype IgnoredPkg struct{ Name string `lua:\"name\"` }\nIgnored []IgnoredPkg `lua:\"ignored\"`","handlingStrategy":"validation","validationCode":"func isStructSlice(f any) bool {\n    t := reflect.TypeOf(f)\n    if t == nil || t.Kind() != reflect.Slice { return false }\n    return t.Elem().Kind() == reflect.Struct\n}","typeGuard":"func sliceOfStruct(f reflect.StructField) bool {\n    return f.Type.Kind() == reflect.Slice && f.Type.Elem().Kind() == reflect.Struct\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"unsupported slice element kind\") {\n    return fmt.Errorf(\"lua settings require []Struct fields: %w\", err)\n}","preventionTips":["Never use []string/[]int for lua-tagged fields","Define a small entry struct with a lua:\"name\" field for list options","Test struct-slice fields with a canary init.lua"],"tags":["go","reflection","unsupported-type"],"backgroundTag":"unsupported-operation","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"}