Tencent/WeKnora · error

database %s has no data sources

Error message

database %s has no data sources

What it means

QueryDatabaseAll queries a Notion database by trying the id as a data_source_id first; on 404 it falls back to treating the id as a database container ID and resolves it via GET /v1/databases/{id}. If that database object exists but its data_sources list is empty (info.DataSourceID == ""), the client cannot identify any data source to POST /v1/data_sources/{id}/query against, so it throws this error. In practice this means the id is a valid database container but Notion's API model exposes no queryable data source for it (API-version drift or an empty/deleted database).

Source

Thrown at internal/datasource/connector/notion/client.go:357

}

// QueryDatabaseAll retrieves all records from a database via POST /v1/data_sources/{id}/query.
// Accepts either a data_source_id (from search) or a database_id (from child_database blocks).
// For database_ids, resolves to data_source_id via GET /v1/databases/{id}.
func (c *notionClient) QueryDatabaseAll(ctx context.Context, id string) ([]notionPage, error) {
	// Try as data_source_id directly
	records, err := c.paginatePages(ctx, http.MethodPost, fmt.Sprintf("/v1/data_sources/%s/query", id))
	if err == nil {
		return records, nil
	}

	// If 404, id might be a database container ID — resolve to data_source_id
	info, dbErr := c.GetDatabaseInfo(ctx, id)
	if dbErr != nil {
		return nil, fmt.Errorf("query database %s: not a data_source (%v) and not a database (%v)", id, err, dbErr)
	}
	if info.DataSourceID == "" {
		return nil, fmt.Errorf("database %s has no data sources", id)
	}
	return c.paginatePages(ctx, http.MethodPost, fmt.Sprintf("/v1/data_sources/%s/query", info.DataSourceID))
}

// ResolveBlock re-fetches a single block to resolve file_upload URLs.
// When a block contains a file_upload type, re-fetching it returns the resolved
// download URL (temporary S3 signed URL, 1-hour expiry).
func (c *notionClient) ResolveBlock(ctx context.Context, blockID string) (*notionBlock, error) {
	respBody, err := c.doRequest(ctx, http.MethodGet, "/v1/blocks/"+blockID, nil)
	if err != nil {
		return nil, err
	}
	var block notionBlock
	if err := json.Unmarshal(respBody, &block); err != nil {
		return nil, fmt.Errorf("unmarshal block: %w", err)
	}
	return &block, nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Re-fetch the database id from the Notion search endpoint or a fresh child_database block to get a current data_source_id and pass that to QueryDatabaseAll.
  2. Open the database in Notion and confirm it still contains at least one data source (not deleted/emptied); restore or recreate it if so.
  3. If you control the integration, pin a Notion API version where databases still expose data_sources, or update notionBlock/notionDatabase parsing so DataSourceID is extracted from the new response shape.
  4. Check that GetDatabaseInfo unmarshals the data_sources array correctly — an empty DataSourceID may indicate a struct-field mismatch (e.g. wrong JSON tag) rather than a truly empty database.

Example fix

// before
records, err := client.QueryDatabaseAll(ctx, "a1b2c3d4e5f6..." ) // old cached database container id
// after
dataSourceID := "f6e5d4c3b2a1..." // from search result or block data_source.id
records, err := client.QueryDatabaseAll(ctx, dataSourceID)
Defensive patterns

Strategy: validation

Validate before calling

if id == "" {
    return fmt.Errorf("database id is required")
}
// prefer data_source ids obtained from search / child_database blocks:
if !strings.Contains(id, "data_source") && dataSourceID != "" {
    id = dataSourceID
}

Type guard

func hasDataSource(info *notionDatabaseInfo) bool {
    return info != nil && info.DataSourceID != ""
}

Try / catch

records, err := client.QueryDatabaseAll(ctx, id)
if err != nil {
    if strings.Contains(err.Error(), "has no data sources") {
        // fall back to re-resolving the id via search or skip the database
        logger.Warnf(ctx, "skipping database %s: no data sources", id)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling QueryDatabaseAll(ctx, id) where id is a database container ID (e.g. from a child_database block) whose GET /v1/databases/{id} response has an empty data_sources array — i.e. info.DataSourceID is empty. Requires the initial data_source query attempt to have failed with 404 first.

Common situations: Using an old database_id cached before Notion moved querying to the data_sources endpoint (API version 2022-06-28 vs newer 2025-09-03-style layouts); the database was emptied/deleted so its only data source was removed; copying a database container URL id instead of the data_source id from search results.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/61e5997ee42dd1c5. Report an issue: GitHub.