Tencent/WeKnora · error
unmarshal page: %w
Error message
unmarshal page: %w
What it means
GetPage fetched a page successfully from /v1/pages/{id} but json.Unmarshal of the response into the notionPage struct failed. This indicates the response body is not valid JSON or its shape doesn't match notionPage's typed fields. The doRequest call itself succeeded, so auth and network were fine.
Source
Thrown at internal/datasource/connector/notion/client.go:174
_, err := c.doRequest(ctx, http.MethodGet, "/v1/users/me", nil)
return err
}
// SearchPages returns all pages and databases accessible to the integration.
func (c *notionClient) SearchPages(ctx context.Context) ([]notionPage, error) {
return c.paginatePages(ctx, http.MethodPost, "/v1/search")
}
// GetPage retrieves a single page by ID.
func (c *notionClient) GetPage(ctx context.Context, pageID string) (*notionPage, error) {
respBody, err := c.doRequest(ctx, http.MethodGet, "/v1/pages/"+pageID, nil)
if err != nil {
return nil, err
}
var page notionPage
if err := json.Unmarshal(respBody, &page); err != nil {
return nil, fmt.Errorf("unmarshal page: %w", err)
}
page.Title = extractTitle(&page)
return &page, nil
}
// 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
}View on GitHub (pinned to 988cbb0330)
Solutions
- Print/log the raw respBody on failure to see what was actually returned — usually reveals HTML or unexpected JSON.
- Verify baseURL is https://api.notion.com (or a faithful proxy) and not intercepting with 200 responses.
- Pin NotionAPIVersion to a version compatible with the notionPage struct; update struct tags if you upgrade the API version.
- Check that no proxy injects content (disable HTTPS interception or trust the proxy's CA properly).
Defensive patterns
Strategy: type-guard
Type guard
func isLikelyJSON(b []byte) bool {
t := bytes.TrimSpace(b)
return len(t) > 0 && (t[0] == '{' || t[0] == '[')
}
// usage: if !isLikelyJSON(respBody) { /* proxy/HTML interference */ } Try / catch
page, err := client.GetPage(ctx, pageID)
if err != nil && strings.HasPrefix(err.Error(), "unmarshal page:") {
// log raw response via tracing middleware; suspect proxy or schema drift
log.Printf("non-conforming page response: %v", err)
} Prevention
- Use the official baseURL (https://api.notion.com/v1) — avoid 200-response interceptors
- Pin NotionAPIVersion and test struct compatibility after version upgrades
- Add a debug mode that logs raw bodies on unmarshal failure
- Keep notionPage struct tags updated when fields are added to the client
When it happens
Trigger: GET /v1/pages/{pageID} returns a body that fails to decode into notionPage — e.g. an HTML error page from a proxy (2xx but not JSON), or a Notion response whose typed fields (created_time, last_edited_time, etc.) change shape in a new API version while Notion-Version header pins an older version.
Common situations: A reverse proxy or captive portal returning 200 with HTML instead of JSON; Notion API version drift changing response schemas; corrupted gzip/encoding handling by an intermediary; baseURL accidentally pointing at a non-Notion service that answers 200 with other content.
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 database: %w
- unmarshal data_source: %w
- unmarshal block children response: %w
- unmarshal page results: %w
- unmarshal data_sources: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/960e1ab8c5acfd6b.
Report an issue: GitHub.