{"record":{"id":"10bb7a31ac3c0bb9","repo":"gastownhall/beads","slug":"resolve-q-as-data-source-w-as-database-v","errorCode":null,"errorMessage":"resolve %q as data source: %w; as database: %v","messagePattern":"resolve %q as data source: %w; as database: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/notion/client.go","lineNumber":224,"sourceCode":"func ResolveDataSourceReference(ctx context.Context, client DataSourceResolver, ref string) (*ResolvedDataSource, error) {\n\tif client == nil {\n\t\treturn nil, fmt.Errorf(\"notion client is nil\")\n\t}\n\tidentifier := ExtractNotionIdentifier(ref)\n\tif identifier == \"\" {\n\t\treturn nil, fmt.Errorf(\"could not extract a Notion ID from %q\", ref)\n\t}\n\tif ds, err := client.RetrieveDataSource(ctx, identifier); err == nil {\n\t\treturn &ResolvedDataSource{\n\t\t\tInputID:      identifier,\n\t\t\tDataSourceID: ds.ID,\n\t\t\tDataSource:   ds,\n\t\t\tViewURL:      strings.TrimSpace(ref),\n\t\t}, nil\n\t} else {\n\t\tdb, dbErr := client.RetrieveDatabase(ctx, identifier)\n\t\tif dbErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"resolve %q as data source: %w; as database: %v\", ref, err, dbErr)\n\t\t}\n\t\tif len(db.DataSources) == 0 || strings.TrimSpace(db.DataSources[0].ID) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"database %s has no child data sources\", db.ID)\n\t\t}\n\t\tresolvedID := strings.TrimSpace(db.DataSources[0].ID)\n\t\tresolvedDS, err := client.RetrieveDataSource(ctx, resolvedID)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"retrieve child data source %s: %w\", resolvedID, err)\n\t\t}\n\t\treturn &ResolvedDataSource{\n\t\t\tInputID:      identifier,\n\t\t\tDataSourceID: resolvedID,\n\t\t\tDataSource:   resolvedDS,\n\t\t\tDatabase:     db,\n\t\t\tViewURL:      strings.TrimSpace(ref),\n\t\t}, nil\n\t}\n}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/notion/client.go#L206-L242","documentation":"ResolveDataSourceReference tries RetrieveDataSource first; on failure it falls back to RetrieveDatabase. If the database lookup also fails it returns this combined error carrying both the data-source error (%w, unwrap target) and the database error (%v). It means the identifier matched neither a data source nor a database the token can read.","triggerScenarios":"Calling ResolveDataSourceReference with an ID that is neither a data source nor a database (e.g. a page ID), or with an ID the integration token cannot access — both RetrieveDataSource and RetrieveDatabase return 404/401.","commonSituations":"Sharing a page (not the database) with the integration; forgetting to grant the integration to the workspace/database; the referenced resource was deleted or moved; pointing at a regular page ID expecting database semantics.","solutions":["Open Notion → Connections and share the database (not just the parent page) with the integration.","Verify the ID resolves in the browser and is actually a database/data source, not a plain page.","Check the token is for the correct workspace and has not been revoked; re-issue if needed.","Read the wrapped errors separately (errors.Unwrap / the 'as database:' suffix) to distinguish 401 (permissions) from 404 (wrong object)."],"exampleFix":"// before\nresolved, err := notion.ResolveDataSourceReference(ctx, client, pageIDFromConfig) // page, not database\n// after\n// set the config value to the database/data source URL shared with the integration\nresolved, err := notion.ResolveDataSourceReference(ctx, client, databaseURLSharedWithIntegration)","handlingStrategy":"validation","validationCode":"// before resolving, confirm the integration can see the resource:\n// 1. open the link in a browser as the workspace admin\n// 2. check Notion -> Connections includes the integration on the database","typeGuard":null,"tryCatchPattern":"resolved, err := notion.ResolveDataSourceReference(ctx, client, ref)\nif err != nil {\n    var apiErr *notion.APIError\n    if errors.As(err, &apiErr) && apiErr.Status == 401 {\n        // permissions problem: share the resource with the integration\n    }\n    return err\n}","preventionTips":["Share the database itself (not just the parent page) with the integration","Verify the ID is a database/data source, not a plain page","Check token validity and workspace when onboarding","Inspect both wrapped errors to separate 401 from 404"],"tags":["notion","permissions","api","resource-not-found"],"backgroundTag":"notion-access-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}