Tencent/WeKnora · error

unmarshal data_sources: %w

Error message

unmarshal data_sources: %w

What it means

Second decode step inside GetDatabaseInfo: after the notionPage unmarshal succeeds, the same response body is unmarshaled into an anonymous struct with a `data_sources` array to extract the data source ID. Failure means the `data_sources` field is present with a non-array/non-object shape, or the body is otherwise incompatible. An empty/missing data_sources key does NOT error — dsID simply stays empty.

Source

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

func (c *notionClient) GetDatabaseInfo(ctx context.Context, dbID string) (*databaseInfo, error) {
	respBody, err := c.doRequest(ctx, http.MethodGet, "/v1/databases/"+dbID, nil)
	if err != nil {
		return nil, err
	}

	var db notionPage
	if err := json.Unmarshal(respBody, &db); err != nil {
		return nil, fmt.Errorf("unmarshal database: %w", err)
	}
	db.Title = extractTitle(&db)

	var dsResult struct {
		DataSources []struct {
			ID string `json:"id"`
		} `json:"data_sources"`
	}
	if err := json.Unmarshal(respBody, &dsResult); err != nil {
		return nil, fmt.Errorf("unmarshal data_sources: %w", err)
	}

	dsID := ""
	if len(dsResult.DataSources) > 0 {
		dsID = dsResult.DataSources[0].ID
	}

	return &databaseInfo{Page: db, DataSourceID: dsID}, nil
}

// GetDataSourceInfo retrieves a data source by ID, returning its metadata.
// In API 2025-09-03+, data_source objects hold the schema/properties and are
// the target for record queries. The response includes database_parent to
// locate the database in the workspace hierarchy.
func (c *notionClient) GetDataSourceInfo(ctx context.Context, dsID string) (*notionPage, error) {
	respBody, err := c.doRequest(ctx, http.MethodGet, "/v1/data_sources/"+dsID, nil)
	if err != nil {
		return nil, err

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check NotionAPIVersion — the data_sources array shape is from API version 2025-09-03+; align the pinned version with the expected schema.
  2. Log respBody to compare the actual data_sources JSON type against the expected [{"id":"..."}].
  3. If data_sources may legitimately be absent, treat this as optional rather than fatal — the code already handles empty arrays at client.go:210.
  4. Update the anonymous struct at client.go:200 to match the actual API response shape.

Example fix

// before: strict anonymous struct
var dsResult struct {
    DataSources []struct {
        ID string `json:"id"`
    } `json:"data_sources"`
}
// after: tolerate raw and parse leniently
var dsResult struct {
    DataSources []json.RawMessage `json:"data_sources"`
}
_ = json.Unmarshal(respBody, &dsResult) // optional field
for _, raw := range dsResult.DataSources {
    var ds struct { ID string `json:"id"` }
    if json.Unmarshal(raw, &ds) == nil && ds.ID != "" { dsID = ds.ID; break }
}
Defensive patterns

Strategy: fallback

Try / catch

info, err := client.GetDatabaseInfo(ctx, dbID)
if err != nil && strings.Contains(err.Error(), "unmarshal data_sources:") {
    // fall back: query without data_source resolution, or refresh API version
    log.Printf("data_sources field missing/malformed for %s; check Notion-Version >= 2025-09-03", dbID)
}

Prevention

When it happens

Trigger: GET /v1/databases/{id} with an API version that returns a differently-shaped data_sources field (e.g. string instead of array of objects, or objects without string id), so json.Unmarshal fails on the anonymous struct. Only reachable when the first notionPage unmarshal succeeded.

Common situations: Pinned Notion-Version older than 2025-09-03 where databases have no data_sources (usually yields empty, not error) vs newer versions changing the field type; proxy-rewritten responses; custom mock servers in tests returning incompatible fixtures.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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