{"record":{"id":"a01fe8355c7f4a55","repo":"Tencent/WeKnora","slug":"errinvalidconfig-a01fe8","errorCode":"ErrInvalidConfig","errorMessage":"%w: config is nil","messagePattern":"%w: config is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/yuque/types.go","lineNumber":67,"sourceCode":"func (c *Config) GetBaseURL() string {\n\turl := strings.TrimSpace(c.BaseURL)\n\tif url == \"\" {\n\t\treturn DefaultBaseURL\n\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","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/yuque/types.go#L49-L85","documentation":"parseYuqueConfig validates the Yuque connector's DataSourceConfig before use. It wraps datasource.ErrInvalidConfig when the config pointer itself is nil, meaning the connector was invoked without any configuration object at all. This is a fail-fast guard: no credentials parsing is attempted without a config.","triggerScenarios":"Calling Validate, ListResources, or walk on the Yuque connector with a nil *types.DataSourceConfig, or an anonymous caller path passing nil config.","commonSituations":"A datasource entry failed to load from config storage but the connector was still invoked; a factory/registry returns the connector but skips config construction; tests or callers construct the adapter without wiring a config.","solutions":["Ensure the DataSourceConfig is loaded/constructed before calling the connector (check registry/store lookup result for nil).","Validate config presence at the call site with a nil check before invoking Validate/ListResources/walk.","Fix upstream config loading so partially-configured datasources are skipped or reported instead of passed through."],"exampleFix":"// before\nconn.ListResources(ctx, nil)\n// after\nif cfg == nil {\n    return fmt.Errorf(\"yuque datasource not configured\")\n}\nconn.ListResources(ctx, cfg)","handlingStrategy":"validation","validationCode":"if config == nil {\n    return fmt.Errorf(\"yuque datasource requires a DataSourceConfig\")\n}","typeGuard":"func hasConfig(c *types.DataSourceConfig) bool { return c != nil }","tryCatchPattern":"cfg, err := parseYuqueConfig(config)\nif err != nil {\n    if errors.Is(err, datasource.ErrInvalidConfig) {\n        // surface a clear \"datasource not configured\" message\n    }\n    return err\n}","preventionTips":["Never invoke connector Validate/ListResources/walk with a nil config; check registry lookup results.","Skip or flag unconfigured datasources at load time.","Add unit tests covering the nil-config path."],"tags":["config","nil","yuque"],"backgroundTag":"nil-config","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}