{"record":{"id":"d88653c5af4537a1","repo":"gastownhall/beads","slug":"could-not-extract-a-notion-id-from-q","errorCode":null,"errorMessage":"could not extract a Notion ID from %q","messagePattern":"could not extract a Notion ID from %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/notion/client.go","lineNumber":212,"sourceCode":"\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) == \"\" {\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)","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/notion/client.go#L194-L230","documentation":"ResolveDataSourceReference first runs the reference string through ExtractNotionIdentifier to pull a 32-hex Notion ID (optionally dash-separated) out of a URL or raw string. If nothing ID-shaped is found it returns this error naming the original reference.","triggerScenarios":"Passing a string containing no Notion identifier: an empty string, a bare database title, a non-Notion URL, a URL lacking any 32-character hex ID, or text where the ID was replaced by a workspace/page slug.","commonSituations":"Config values pasted as 'My Team Wiki' or a docs URL (notion.so/Team-Wiki-...) whose slug has no ID; using a redirected short link format; typos stripping the ID from the URL; storing a view name instead of the view URL.","solutions":["Copy the full URL via Notion's 'Copy link' so the trailing 32-hex ID is present.","Extract the ID manually with a regex like [0-9a-f]{32} and pass the raw ID.","Check the configured value in your config/env for truncation or a display-name substitution.","Pre-resolve the reference with notion.ExtractNotionIdentifier in validation code before calling the resolver."],"exampleFix":"// before\nclientCfg.ViewURL = \"https://notion.so/my-team-wiki\" // no ID\n// after\nclientCfg.ViewURL = \"https://notion.so/my-team-wiki-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d\"","handlingStrategy":"validation","validationCode":"if notion.ExtractNotionIdentifier(ref) == \"\" {\n    return fmt.Errorf(\"%q does not contain a Notion ID\", ref)\n}","typeGuard":"func isNotionIDLike(s string) bool {\n    s = strings.ReplaceAll(s, \"-\", \"\")\n    if len(s) != 32 {\n        return false\n    }\n    for _, r := range s {\n        if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f') {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Use Notion's 'Copy link' so URLs carry the 32-hex ID","Validate configured references with ExtractNotionIdentifier at config-load time","Never store display names or slugs in place of URLs","Trim and check the value isn't truncated in config/env"],"tags":["notion","identifier","validation","configuration"],"backgroundTag":"invalid-notion-id","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}