Tencent/WeKnora · error

unmarshal page results: %w

Error message

unmarshal page results: %w

What it means

paginatePages unmarshals resp.Results (a json.RawMessage) into []notionPage. If individual page/database objects don't match the notionPage struct, unmarshal fails with this wrapper. Notion returns polymorphic objects (page vs database vs child_page), so schema drift breaks decoding.

Source

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

		} else {
			p := path
			if startCursor != "" {
				p += "?start_cursor=" + startCursor + "&page_size=100"
			}
			respBody, err = c.doRequest(ctx, method, p, nil)
		}
		if err != nil {
			return nil, fmt.Errorf("paginate %s: %w", path, err)
		}

		var resp paginatedResponse
		if err := json.Unmarshal(respBody, &resp); err != nil {
			return nil, fmt.Errorf("unmarshal paginated response: %w", err)
		}

		var pages []notionPage
		if err := json.Unmarshal(resp.Results, &pages); err != nil {
			return nil, fmt.Errorf("unmarshal page results: %w", err)
		}

		for i := range pages {
			pages[i].Title = extractTitle(&pages[i])
		}

		allPages = append(allPages, pages...)

		if !resp.HasMore || resp.NextCursor == "" {
			break
		}
		startCursor = resp.NextCursor
	}

	return allPages, nil
}

// --- Title extraction helpers ---

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the wrapped json error — it names the offending field and type
  2. Compare the returned JSON against the notionPage struct in types.go
  3. Make strict fields pointers or use json.RawMessage for polymorphic sections
  4. Update connector types to match the current Notion API schema

Example fix

// before
var pages []notionPage
if err := json.Unmarshal(resp.Results, &pages); err != nil {
    return nil, fmt.Errorf("unmarshal page results: %w", err)
}
// after
var raw []json.RawMessage
json.Unmarshal(resp.Results, &raw)
for _, r := range raw {
    var p notionPage
    if err := json.Unmarshal(r, &p); err != nil {
        continue // skip objects that don't fit the schema
    }
    pages = append(pages, p)
}
Defensive patterns

Strategy: type-guard

Validate before calling

var probe struct { Results []json.RawMessage `json:"results"` }; if json.Unmarshal(body, &probe) != nil { return errors.New("unexpected notion response shape") }

Type guard

func isValidNotionPage(raw json.RawMessage) bool {
    var probe struct{ ID string `json:"id"` }
    return json.Unmarshal(raw, &probe) == nil && probe.ID != ""
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unmarshal page results") {
    log.Printf("notion page schema mismatch: %v", err)
    return partialOrEmptyResult // degrade instead of failing sync
}

Prevention

When it happens

Trigger: SearchPages or QueryDatabaseAll receives results whose objects contain unexpected field types (e.g. properties with shapes the notionPage struct doesn't model) or null where a struct is expected.

Common situations: Notion API adds/changes object types returned by the search endpoint; a workspace contains object types (comments, child_database variants) not covered by the struct definitions.

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/9b06151273fed2f3. Report an issue: GitHub.