Tencent/WeKnora · error
no resource IDs (book IDs) configured
Error message
no resource IDs (book IDs) configured
What it means
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.
Source
Thrown at internal/datasource/connector/yuque/connector.go:324
// Namespace may be empty on some responses; fall back to base URL only.
func buildDocURL(baseURL, namespace, slug string) string {
if namespace == "" {
return baseURL
}
return baseURL + "/" + namespace + "/" + slug
}
// FetchIncremental returns items changed (or deleted) since the prior cursor.
// Deletion detection: docs present in the prior cursor but absent from the
// current list are emitted as IsDeleted=true placeholder items.
func (c *Connector) FetchIncremental(
ctx context.Context,
config *types.DataSourceConfig,
cursor *types.SyncCursor,
) ([]types.FetchedItem, *types.SyncCursor, error) {
resourceIDs := config.ResourceIDs
if len(resourceIDs) == 0 {
return nil, nil, fmt.Errorf("no resource IDs (book IDs) configured")
}
// Decode prior cursor (if any).
var prev *yuqueCursor
if cursor != nil && cursor.ConnectorCursor != nil {
var p yuqueCursor
b, _ := json.Marshal(cursor.ConnectorCursor)
_ = json.Unmarshal(b, &p)
prev = &p
}
items, newCursor, err := c.walk(ctx, config, resourceIDs, prev, true)
if err != nil {
return nil, nil, err
}
// Marshal newCursor into a generic map for the SyncCursor wrapper.
cursorMap := make(map[string]interface{})View on GitHub (pinned to 988cbb0330)
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
Example fix
// before
config := &types.DataSourceConfig{Name: "yuque"} // ResourceIDs empty
// after
config := &types.DataSourceConfig{Name: "yuque", ResourceIDs: []string{"12345", "67890"}} Defensive patterns
Strategy: validation
Validate before calling
func validateYuqueConfig(cfg *types.DataSourceConfig) error {
if cfg == nil || len(cfg.ResourceIDs) == 0 {
return fmt.Errorf("yuque datasource requires at least one numeric book ID in ResourceIDs")
}
return nil
} Type guard
func hasResourceIDs(cfg *types.DataSourceConfig) bool {
return cfg != nil && len(cfg.ResourceIDs) > 0
} Try / catch
items, cur, err := ds.FetchIncremental(ctx, cfg, cursor)
if err != nil {
if strings.Contains(err.Error(), "no resource IDs") {
// recover by re-running resource selection / listing repos first
cfg.ResourceIDs, err = selectBookIDs(ctx, cfg)
if err != nil {
return err
}
items, cur, err = ds.FetchIncremental(ctx, cfg, cursor)
}
if err != nil {
return err
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- invalid book id %q: %w
- sandbox: config is missing required fields
- S3 access key and secret key must be provided together
- ErrNamedSandboxBackendUnsupported
- API key is required for Ollama provider
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/a5bee60a3d6ccb5d.
Report an issue: GitHub.