{"record":{"id":"a5bee60a3d6ccb5d","repo":"Tencent/WeKnora","slug":"no-resource-ids-book-ids-configured","errorCode":null,"errorMessage":"no resource IDs (book IDs) configured","messagePattern":"no resource IDs \\(book IDs\\) configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/yuque/connector.go","lineNumber":324,"sourceCode":"// Namespace may be empty on some responses; fall back to base URL only.\nfunc buildDocURL(baseURL, namespace, slug string) string {\n\tif namespace == \"\" {\n\t\treturn baseURL\n\t}\n\treturn baseURL + \"/\" + namespace + \"/\" + slug\n}\n\n// FetchIncremental returns items changed (or deleted) since the prior cursor.\n// Deletion detection: docs present in the prior cursor but absent from the\n// current list are emitted as IsDeleted=true placeholder items.\nfunc (c *Connector) FetchIncremental(\n\tctx context.Context,\n\tconfig *types.DataSourceConfig,\n\tcursor *types.SyncCursor,\n) ([]types.FetchedItem, *types.SyncCursor, error) {\n\tresourceIDs := config.ResourceIDs\n\tif len(resourceIDs) == 0 {\n\t\treturn nil, nil, fmt.Errorf(\"no resource IDs (book IDs) configured\")\n\t}\n\n\t// Decode prior cursor (if any).\n\tvar prev *yuqueCursor\n\tif cursor != nil && cursor.ConnectorCursor != nil {\n\t\tvar p yuqueCursor\n\t\tb, _ := json.Marshal(cursor.ConnectorCursor)\n\t\t_ = json.Unmarshal(b, &p)\n\t\tprev = &p\n\t}\n\n\titems, newCursor, err := c.walk(ctx, config, resourceIDs, prev, true)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Marshal newCursor into a generic map for the SyncCursor wrapper.\n\tcursorMap := make(map[string]interface{})","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/yuque/connector.go#L306-L342","documentation":"FetchIncremental requires config.ResourceIDs to list which Yuque books (repos) to sync. This error is thrown when ResourceIDs is empty, since incremental sync has no defined scope of books to walk. It is a configuration guard, not an API failure.","triggerScenarios":"A DataSourceConfig is passed to FetchIncremental with ResourceIDs nil or length 0 — e.g. the datasource was created without selecting any books, or ResourceIDs was cleared by a config update.","commonSituations":"Connector registered without completing the resource-selection step; admin cleared the book selection in the datasource UI; config deserialization dropped an empty/missing resource_ids field.","solutions":["Configure ResourceIDs in the datasource config with the numeric Yuque book IDs to sync","Re-run the datasource setup/resource selection flow and save at least one book","If syncing all repos is intended, populate ResourceIDs from ListResources results instead of leaving it empty","Validate config on save (reject empty ResourceIDs) so the error surfaces at configuration time"],"exampleFix":"// before\nconfig := &types.DataSourceConfig{Name: \"yuque\"} // ResourceIDs empty\n// after\nconfig := &types.DataSourceConfig{Name: \"yuque\", ResourceIDs: []string{\"12345\", \"67890\"}}","handlingStrategy":"validation","validationCode":"func validateYuqueConfig(cfg *types.DataSourceConfig) error {\n    if cfg == nil || len(cfg.ResourceIDs) == 0 {\n        return fmt.Errorf(\"yuque datasource requires at least one numeric book ID in ResourceIDs\")\n    }\n    return nil\n}","typeGuard":"func hasResourceIDs(cfg *types.DataSourceConfig) bool {\n    return cfg != nil && len(cfg.ResourceIDs) > 0\n}","tryCatchPattern":"items, cur, err := ds.FetchIncremental(ctx, cfg, cursor)\nif err != nil {\n    if strings.Contains(err.Error(), \"no resource IDs\") {\n        // recover by re-running resource selection / listing repos first\n        cfg.ResourceIDs, err = selectBookIDs(ctx, cfg)\n        if err != nil {\n            return err\n        }\n        items, cur, err = ds.FetchIncremental(ctx, cfg, cursor)\n    }\n    if err != nil {\n        return err\n    }\n}","preventionTips":["Reject datasource configs with empty ResourceIDs at save time","Require the resource-selection step to complete before enabling the connector","Warn admins when a config update clears ResourceIDs","Seed ResourceIDs from ListResources output if full-account sync is intended"],"tags":["yuque","config","validation","connector"],"backgroundTag":"missing-resource-ids-config","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}