{"record":{"id":"c4f8614b7934841c","repo":"Tencent/WeKnora","slug":"marshal-credentials-w-c4f861","errorCode":null,"errorMessage":"marshal credentials: %w","messagePattern":"marshal credentials: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/yuque/types.go","lineNumber":71,"sourceCode":"\t}\n\tif !strings.Contains(url, \"://\") {\n\t\turl = \"https://\" + url\n\t}\n\turl = strings.TrimRight(url, \"/\")\n\treturn url\n}\n\n// parseYuqueConfig extracts and validates Yuque-specific configuration.\n// Uses JSON marshal/unmarshal roundtrip (consistent with Feishu's parseFeishuConfig)\n// rather than single-field type assertion, because we have multiple fields with\n// optional defaults.\nfunc parseYuqueConfig(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 yuque credentials: %w\", err)\n\t}\n\tif strings.TrimSpace(cfg.APIToken) == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: api_token is required\", datasource.ErrInvalidCredentials)\n\t}\n\tif err := datasource.ValidateConnectorBaseURL(cfg.GetBaseURL()); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &cfg, nil\n}\n\n// --- Yuque API response types ---\n\n// flexibleStatus accepts either a string (\"1\") or a number (1) for the doc\n// `status` field. Yuque's OpenAPI spec declares `status` as string, but the","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/yuque/types.go#L53-L89","documentation":"parseYuqueConfig marshals the raw credentials map to JSON before unmarshalling into the typed Config struct. This error wraps any failure from json.Marshal(config.Credentials), which in practice is extremely rare for map/slice credential values. It indicates the stored credentials value is of a type that cannot be JSON-encoded.","triggerScenarios":"config.Credentials contains a value json.Marshal cannot encode (e.g. a channel, func, or cyclic structure) rather than a normal map[string]interface{} of string credentials.","commonSituations":"Credentials were programmatically constructed with unsupported types instead of being decoded from JSON/YAML config; a custom credential store returned an exotic Go type.","solutions":["Inspect what type the credential store returns; ensure it is a JSON-encodable map or struct.","Log the Go type of config.Credentials and fix the loader to decode into map[string]any.","If wrapping a lower-level error, fix that underlying cause first — this line only re-wraps it."],"exampleFix":"// before\ncreds := map[string]any{\"api_token\": make(chan int)}\n// after\ncreds := map[string]any{\"api_token\": \"your-token\"}","handlingStrategy":"validation","validationCode":"if _, err := json.Marshal(config.Credentials); err != nil {\n    return fmt.Errorf(\"credentials not JSON-encodable: %w\", err)\n}","typeGuard":"func isJSONEncodable(v any) bool { _, err := json.Marshal(v); return err == nil }","tryCatchPattern":"if _, err := json.Marshal(config.Credentials); err != nil {\n    log.Printf(\"unsupported credentials type %T\", config.Credentials)\n    return err\n}","preventionTips":["Keep credentials as map[string]any or a plain struct loaded from JSON/YAML.","Never inject channels, funcs, or cyclic values into credentials.","Type-check credential values at the config loader boundary."],"tags":["json","serialization","credentials"],"backgroundTag":"json-marshal-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}