Tencent/WeKnora · error

unmarshal database: %w

Error message

unmarshal database: %w

What it means

GetDatabaseInfo fetched /v1/databases/{dbID} successfully but the body could not be unmarshaled into notionPage. The database metadata response doesn't match the expected struct shape. Note GetDatabaseInfo also does a second unmarshal for data_sources (error 686); this one covers the main notionPage decode.

Source

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

}

// databaseInfo holds both the metadata and the data source ID from a single API call.
type databaseInfo struct {
	Page         notionPage
	DataSourceID string
}

// GetDatabaseInfo retrieves a database container by ID, returning both
// the page metadata and the primary data source ID in a single API call.
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

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log the raw response body to see the actual payload shape.
  2. Ensure NotionAPIVersion is consistent with the databases endpoint schema (data_sources fields require 2025-09-03+).
  3. Confirm the ID is a database ID; if unsure use QueryDatabaseAll's fallback path which tries data_source first then resolves via GetDatabaseInfo.
  4. Update notionPage struct tags if the API version was upgraded and fields changed.
Defensive patterns

Strategy: type-guard

Type guard

func isLikelyJSON(b []byte) bool {
    t := bytes.TrimSpace(b)
    return len(t) > 0 && (t[0] == '{' || t[0] == '[')
}

Try / catch

info, err := client.GetDatabaseInfo(ctx, dbID)
if err != nil && strings.HasPrefix(err.Error(), "unmarshal database:") {
    // inspect raw body / check API version alignment
    return fmt.Errorf("database response shape mismatch for %s: %w", dbID, err)
}

Prevention

When it happens

Trigger: GET /v1/databases/{id} returns non-JSON or JSON whose top-level fields conflict with notionPage's typed fields (e.g. title/properties as unexpected types, or a 200 body from a proxy). Called from QueryDatabaseAll and getDatabaseOrDataSourceInfo during sync.

Common situations: Notion API version mismatch: older pinned Notion-Version returning database objects with a different schema; ID points to a page (not database) whose response still decodes but here would only fail on shape mismatch; HTML from an intercepting proxy with 200 status.

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/1ee89bfaab8687de. Report an issue: GitHub.