{"record":{"id":"fe853520e5c98832","repo":"Tencent/WeKnora","slug":"errinvalidcredentials","errorCode":"ErrInvalidCredentials","errorMessage":"%w: feed_urls is required","messagePattern":"%w: feed_urls is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/rss/types.go","lineNumber":71,"sourceCode":"\n// parseConfig extracts and validates RSS configuration.\nfunc parseConfig(config *types.DataSourceConfig) (*Config, error) {\n\tif config == nil {\n\t\treturn nil, fmt.Errorf(\"%w: config is nil\", datasource.ErrInvalidConfig)\n\t}\n\tcredBytes, err := json.Marshal(config.Credentials)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal credentials: %w\", err)\n\t}\n\tvar cfg Config\n\tif err := json.Unmarshal(credBytes, &cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse rss credentials: %w\", err)\n\t}\n\tif urls := feedURLsFromSettings(config.Settings); urls != \"\" {\n\t\tcfg.FeedURLs = urls\n\t}\n\tif len(cfg.feedURLList()) == 0 {\n\t\treturn nil, fmt.Errorf(\"%w: feed_urls is required\", datasource.ErrInvalidCredentials)\n\t}\n\treturn &cfg, nil\n}\n\nfunc feedURLsFromSettings(settings map[string]interface{}) string {\n\tif len(settings) == 0 {\n\t\treturn \"\"\n\t}\n\traw, ok := settings[\"feed_urls\"]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\ts, ok := raw.(string)\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn strings.TrimSpace(s)\n}","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/rss/types.go#L53-L89","documentation":"parseConfig validates that at least one RSS feed URL is configured. After merging feed URLs from Settings and Credentials, if feedURLList() is empty it wraps datasource.ErrInvalidCredentials with \"feed_urls is required\". The connector cannot operate without at least one feed to fetch.","triggerScenarios":"Creating/updating an RSS datasource where neither config.Settings['feed_urls'] nor credentials contain feed URLs; Validate, ListResources, or a walk invoked on such a source.","commonSituations":"A user saved the RSS source without filling in the feed URL field; the feed URL was placed under a wrong settings key after a UI rename; a legacy source kept URLs only in credentials while settings handling moved; copy-paste omitted the comma-separated list.","solutions":["Set feed_urls in the datasource settings (or credentials) to a non-empty comma-separated list of RSS feed URLs.","Verify the UI/client sends the key exactly as feed_urls in Settings.","Re-save the datasource through the configuration UI to regenerate the credentials payload.","If migrating legacy sources, copy feed URLs from credentials into Settings."],"exampleFix":"// before\nsettings := map[string]interface{}{}\n// after\nsettings := map[string]interface{}{\n    \"feed_urls\": \"https://example.com/feed.xml, https://other.example/rss\",\n}","handlingStrategy":"validation","validationCode":"urls := settings[\"feed_urls\"]\nu, _ := urls.(string)\nif strings.TrimSpace(u) == \"\" {\n    return errors.New(\"feed_urls is required: provide a comma-separated list of RSS feed URLs\")\n}","typeGuard":"func hasFeedURLs(settings map[string]interface{}) bool {\n    s, ok := settings[\"feed_urls\"].(string)\n    return ok && strings.TrimSpace(s) != \"\"\n}","tryCatchPattern":"cfg, err := parseConfig(config)\nif errors.Is(err, datasource.ErrInvalidCredentials) {\n    // return a 4xx-style \"missing feed_urls\" message to the user\n    return err\n}","preventionTips":["Make feed_urls a required field in the datasource creation form/API.","Validate on the client before submit: at least one non-empty URL.","Provide sensible defaults or example feed URLs in docs."],"tags":["go","validation","rss","missing-config"],"backgroundTag":"missing-required-config-field","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}