{"record":{"id":"de6e98efbc5186cf","repo":"Tencent/WeKnora","slug":"marshal-credentials-w-de6e98","errorCode":null,"errorMessage":"marshal credentials: %w","messagePattern":"marshal credentials: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/rss/types.go","lineNumber":61,"sourceCode":"// because they may carry secrets that must be encrypted at rest. Credentials\n// may still carry feed_urls for backward compatibility with older rows.\ntype Config struct {\n\t// FeedURLs is a newline- or comma-separated list of feed URLs.\n\tFeedURLs string `json:\"feed_urls\"`\n\n\t// AuthHeaders is an optional newline-separated list of custom request\n\t// headers in \"Name: Value\" form, applied only to feed fetches.\n\tAuthHeaders string `json:\"auth_headers,omitempty\"`\n}\n\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}","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/rss/types.go#L43-L79","documentation":"parseConfig marshals config.Credentials (a map[string]interface{}) to JSON before decoding it into the connector's Config struct. If json.Marshal of the credentials fails, the error is wrapped as \"marshal credentials: %w\". Marshaling a map[string]interface{} rarely fails, but it can when credentials contain values unsupported by the JSON encoder (e.g. NaN/Inf floats, channels, funcs) injected by a plugin or upstream decoder.","triggerScenarios":"config.Credentials contains a value type that encoding/json cannot marshal — e.g. a float NaN/Inf produced by an upstream computation, a channel/func value smuggled into the map via a custom decoder, or a cyclic structure if the map type ever changes.","commonSituations":"Credentials built programmatically from parsed YAML/ini where numbers decoded to NaN; custom secret resolvers injecting non-JSON-serializable objects; a corrupt in-memory credentials map.","solutions":["Log/inspect the credentials map (redacting secrets) and remove or fix the non-JSON-serializable value.","Fix the upstream code that populates Credentials so only JSON-safe types (string, bool, numbers, nested maps/slices) are inserted.","If numbers are suspect, sanitize NaN/Inf to 0 or a string before assigning Credentials.","Update the saved datasource record in the database so it stores valid JSON credentials."],"exampleFix":"// before\ncfg.Credentials[\"timeout\"] = math.NaN() // marshal fails\n// after\nt := cfg.Credentials[\"timeout\"]\nif f, ok := t.(float64); ok && (math.IsNaN(f) || math.IsInf(f, 0)) {\n    cfg.Credentials[\"timeout\"] = 0\n}","handlingStrategy":"validation","validationCode":"if _, err := json.Marshal(config.Credentials); err != nil {\n    return fmt.Errorf(\"credentials are not JSON-serializable: %w\", err)\n}","typeGuard":"func jsonSafe(v interface{}) bool {\n    switch v.(type) {\n    case string, bool, int, int64, float64, map[string]interface{}, []interface{}, nil:\n        return true\n    }\n    return false\n}","tryCatchPattern":"cfg, err := parseConfig(config)\nif err != nil && strings.HasPrefix(err.Error(), \"marshal credentials\") {\n    // re-save or repair the datasource credentials payload\n    return err\n}","preventionTips":["Only store JSON-primitive values in Credentials maps.","Sanitize numbers (NaN/Inf) before assigning to Credentials.","Round-trip credentials through json.Marshal at write time to catch bad values early."],"tags":["go","json","serialization","rss"],"backgroundTag":"json-serialization-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}