{"record":{"id":"17f75ec740b3debc","repo":"gastownhall/beads","slug":"notion-client-is-nil","errorCode":null,"errorMessage":"notion client is nil","messagePattern":"notion client is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/notion/client.go","lineNumber":208,"sourceCode":"\treturn &page, nil\n}\n\ntype DataSourceResolver interface {\n\tRetrieveDataSource(ctx context.Context, dataSourceID string) (*DataSource, error)\n\tRetrieveDatabase(ctx context.Context, databaseID string) (*Database, error)\n}\n\ntype ResolvedDataSource struct {\n\tInputID      string\n\tDataSourceID string\n\tDataSource   *DataSource\n\tDatabase     *Database\n\tViewURL      string\n}\n\nfunc 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) == \"\" {","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/notion/client.go#L190-L226","documentation":"ResolveDataSourceReference requires a non-nil DataSourceResolver to call RetrieveDataSource/RetrieveDatabase. If the client argument is nil it fails fast with this error instead of panicking on a nil interface call.","triggerScenarios":"Calling notion.ResolveDataSourceReference with a nil client or a nil-typed interface value — e.g. the client was never constructed because config/token loading failed earlier and the nil was passed through.","commonSituations":"Constructor errors swallowed upstream so the code proceeds with a nil *notion.Client; optional integration wiring where Notion is unconfigured but the resolver is still invoked; test fixtures forgetting to initialize the client.","solutions":["Construct the client with notion.NewClient(token) before resolving references and propagate any constructor error.","Guard the call site: skip resolution (or return a config error) when Notion is not configured.","Check that the variable holding the client is typed as an interface, not a typed-nil pointer like (*notion.Client)(nil).","Log client initialization failures where they happen instead of deferring to the resolve call."],"exampleFix":"// before\nresolved, err := notion.ResolveDataSourceReference(ctx, client, viewURL) // client may be nil\n// after\nif client == nil {\n    return nil, fmt.Errorf(\"notion integration not configured: missing client\")\n}\nresolved, err := notion.ResolveDataSourceReference(ctx, client, viewURL)","handlingStrategy":"validation","validationCode":"if client == nil {\n    return fmt.Errorf(\"notion client not configured\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Handle constructor errors immediately; never pass a possibly-nil client onward","Distinguish 'integration not configured' from runtime failures at the call site","Avoid typed-nil interface values ((*notion.Client)(nil))","Initialize clients once at startup and fail fast"],"tags":["notion","nil-check","configuration","guard"],"backgroundTag":"nil-client","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}