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, errView on GitHub (pinned to 988cbb0330)
Solutions
- Check NotionAPIVersion — the data_sources array shape is from API version 2025-09-03+; align the pinned version with the expected schema.
- Log respBody to compare the actual data_sources JSON type against the expected [{"id":"..."}].
- If data_sources may legitimately be absent, treat this as optional rather than fatal — the code already handles empty arrays at client.go:210.
- 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
- Use Notion API version 2025-09-03+ so databases expose data_sources
- Handle the empty-DataSourceID case (client.go:210) as a legitimate outcome
- Keep anonymous decode structs aligned with the pinned API version
- Test against live API fixtures, not hand-written mocks, after version bumps
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
- unmarshal data_source: %w
- unmarshal page: %w
- unmarshal database: %w
- unmarshal block children response: %w
- unmarshal block: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/79d9cb78b40fc590.
Report an issue: GitHub.