{"record":{"id":"514c0247f8943a66","repo":"Tencent/WeKnora","slug":"unmarshal-block-children-response-w","errorCode":null,"errorMessage":"unmarshal block children response: %w","messagePattern":"unmarshal block children response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/notion/client.go","lineNumber":254,"sourceCode":"// fetching the full block tree content.\nfunc (c *notionClient) GetBlockChildrenFlat(ctx context.Context, blockID string) ([]notionBlock, error) {\n\tvar allBlocks []notionBlock\n\tvar startCursor string\n\n\tfor {\n\t\tpath := fmt.Sprintf(\"/v1/blocks/%s/children\", blockID)\n\t\tif startCursor != \"\" {\n\t\t\tpath += \"?start_cursor=\" + startCursor\n\t\t}\n\n\t\trespBody, err := c.doRequest(ctx, http.MethodGet, path, nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"get block children for %s: %w\", blockID, err)\n\t\t}\n\n\t\tvar resp paginatedResponse\n\t\tif err := json.Unmarshal(respBody, &resp); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unmarshal block children response: %w\", err)\n\t\t}\n\n\t\tvar blocks []notionBlock\n\t\tif err := json.Unmarshal(resp.Results, &blocks); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unmarshal blocks: %w\", err)\n\t\t}\n\n\t\tallBlocks = append(allBlocks, blocks...)\n\n\t\tif !resp.HasMore || resp.NextCursor == \"\" {\n\t\t\tbreak\n\t\t}\n\t\tstartCursor = resp.NextCursor\n\t}\n\n\treturn allBlocks, nil\n}\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/notion/client.go#L236-L272","documentation":"GetBlockChildrenFlat received a 2xx response from /v1/blocks/{id}/children but json.Unmarshal into paginatedResponse failed — the body isn't the expected {results, has_more, next_cursor} envelope. The HTTP call succeeded (doRequest returned no error), so this is purely a response-shape problem.","triggerScenarios":"The children endpoint returns non-JSON (proxy HTML with 200 status) or a JSON body whose results/has_more/next_cursor fields have incompatible types (e.g. results as an object instead of array). Fired per pagination iteration.","commonSituations":"Intercepting proxy or captive portal returning 200 HTML; Notion API version bump changing the pagination envelope; mock/test servers with outdated fixtures; corrupted transfer encoding handled incorrectly by an intermediary.","solutions":["Log the raw respBody on failure — HTML indicates a proxy/interception problem, odd JSON indicates schema drift.","Verify baseURL points at api.notion.com (or a transparent proxy) and TLS is not being intercepted without proper CA trust.","Check paginatedResponse struct tags against the current Notion API pagination envelope; update if the API version changed.","Ensure the block ID in the path didn't get mangled (a bad URL would normally 404, but a misconfigured gateway could 200 with an error page)."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isLikelyJSON(b []byte) bool {\n    t := bytes.TrimSpace(b)\n    return len(t) > 0 && (t[0] == '{' || t[0] == '[')\n}","tryCatchPattern":"blocks, err := client.GetBlockChildrenFlat(ctx, blockID)\nif err != nil && strings.HasPrefix(err.Error(), \"unmarshal block children response:\") {\n    // 200-but-not-JSON or envelope drift: inspect raw body, verify baseURL\n    return fmt.Errorf(\"malformed children response for %s: %w\", blockID, err)\n}","preventionTips":["Route directly to api.notion.com without response-rewriting proxies","Keep paginatedResponse struct tags matched to the pinned API version","Log raw bodies on unmarshal failures to distinguish HTML vs schema drift","Validate fixtures against the live API in CI before releases"],"tags":["notion","json","unmarshal","pagination","schema"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}