{"record":{"id":"1a62d30630e04a7e","repo":"gohugoio/hugo","slug":"permalinks-pattern-must-be-a-string-got-t","errorCode":null,"errorMessage":"permalinks: pattern must be a string, got %T","messagePattern":"permalinks: pattern must be a string, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/page/permalinks.go","lineNumber":552,"sourceCode":"\nfunc decodePermalinksSlice(ms []map[string]any) (PermalinksConfig, error) {\n\tvar configs PermalinksConfig\n\tfor _, m := range ms {\n\t\tm = hmaps.CleanConfigStringMap(m)\n\t\tvar cfg PermalinkConfig\n\n\t\tif targetVal, ok := m[\"target\"]; ok {\n\t\t\tif err := mapstructure.WeakDecode(targetVal, &cfg.Target); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"permalinks: failed to decode target: %w\", err)\n\t\t\t}\n\t\t\tcfg.Target.Kind = strings.ToLower(cfg.Target.Kind)\n\t\t\tcfg.Target.Path = filepath.ToSlash(strings.ToLower(cfg.Target.Path))\n\t\t}\n\n\t\tif patternVal, ok := m[\"pattern\"]; ok {\n\t\t\tcfg.Pattern, ok = patternVal.(string)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"permalinks: pattern must be a string, got %T\", patternVal)\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"permalinks: missing pattern\")\n\t\t}\n\n\t\tconfigs = append(configs, cfg)\n\t}\n\n\treturn configs, nil\n}\n\nfunc decodePermalinksMap(m map[string]any) (PermalinksConfig, error) {\n\tvar configs PermalinksConfig\n\tconfig := hmaps.CleanConfigStringMap(m)\n\n\tfor k, v := range config {\n\t\tswitch v := v.(type) {\n\t\tcase string:","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/page/permalinks.go#L534-L570","documentation":"Thrown by decodePermalinksSlice when a permalink rule has a 'pattern' key but its value is not a string (the type assertion patternVal.(string) fails). Patterns must be strings containing permalink tokens like /:year/:slug/.","triggerScenarios":"A list-format permalink rule writes pattern as a number, list, or map, e.g. pattern = [\"/:year/:slug/\"] (a list) or pattern = 42.","commonSituations":"Quoting mistakes, YAML list-ifying a single pattern, or JSON config where the pattern value is an array.","solutions":["Set 'pattern' to a single string value.","If you need multiple patterns, add separate [[permalinks]] rules instead.","Double-check quoting in YAML/TOML so the pattern is parsed as a string."],"exampleFix":"# before\n[[permalinks]]\ntarget = { path = \"/posts/**\" }\npattern = [\"/:year/:slug/\"]\n# after\n[[permalinks]]\ntarget = { path = \"/posts/**\" }\npattern = \"/:year/:slug/\"","handlingStrategy":"type-guard","validationCode":"if pv, ok := m[\"pattern\"]; ok {\n    if _, ok := pv.(string); !ok {\n        return fmt.Errorf(\"pattern must be string, got %T\", pv)\n    }\n}","typeGuard":"func patternIsString(m map[string]any) bool {\n    v, ok := m[\"pattern\"]\n    return ok && reflect.TypeOf(v).Kind() == reflect.String\n}","tryCatchPattern":"cfg, err := page.DecodePermalinksConfig(raw)\nif err != nil { /* quote pattern / split into multiple rules */ }","preventionTips":["Always quote pattern values as single strings.","Use separate [[permalinks]] rules for multiple patterns.","Validate config quoting in TOML/YAML."],"tags":["hugo","permalinks","configuration","type-mismatch"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}