gastownhall/beads · error
could not extract a Notion ID from %q
Error message
could not extract a Notion ID from %q
What it means
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.
Source
Thrown at internal/notion/client.go:212
RetrieveDataSource(ctx context.Context, dataSourceID string) (*DataSource, error)
RetrieveDatabase(ctx context.Context, databaseID string) (*Database, error)
}
type ResolvedDataSource struct {
InputID string
DataSourceID string
DataSource *DataSource
Database *Database
ViewURL string
}
func ResolveDataSourceReference(ctx context.Context, client DataSourceResolver, ref string) (*ResolvedDataSource, error) {
if client == nil {
return nil, fmt.Errorf("notion client is nil")
}
identifier := ExtractNotionIdentifier(ref)
if identifier == "" {
return nil, fmt.Errorf("could not extract a Notion ID from %q", ref)
}
if ds, err := client.RetrieveDataSource(ctx, identifier); err == nil {
return &ResolvedDataSource{
InputID: identifier,
DataSourceID: ds.ID,
DataSource: ds,
ViewURL: strings.TrimSpace(ref),
}, nil
} else {
db, dbErr := client.RetrieveDatabase(ctx, identifier)
if dbErr != nil {
return nil, fmt.Errorf("resolve %q as data source: %w; as database: %v", ref, err, dbErr)
}
if len(db.DataSources) == 0 || strings.TrimSpace(db.DataSources[0].ID) == "" {
return nil, fmt.Errorf("database %s has no child data sources", db.ID)
}
resolvedID := strings.TrimSpace(db.DataSources[0].ID)
resolvedDS, err := client.RetrieveDataSource(ctx, resolvedID)View on GitHub (pinned to 71377f2769)
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.
Example fix
// before clientCfg.ViewURL = "https://notion.so/my-team-wiki" // no ID // after clientCfg.ViewURL = "https://notion.so/my-team-wiki-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d"
Defensive patterns
Strategy: validation
Validate before calling
if notion.ExtractNotionIdentifier(ref) == "" {
return fmt.Errorf("%q does not contain a Notion ID", ref)
} Type guard
func isNotionIDLike(s string) bool {
s = strings.ReplaceAll(s, "-", "")
if len(s) != 32 {
return false
}
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f') {
return false
}
}
return true
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- identity: invalid proxy secret
- backend must be set
- repo %q must use OWNER/REPO or HOST/OWNER/REPO
- repo %q contains an empty path component
- repo %q contains invalid character %q
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d88653c5af4537a1.
Report an issue: GitHub.