gastownhall/beads · error

Notion token not configured

Error message

Notion token not configured

What it means

The Client exists but its Token field is empty or whitespace-only, so doRequest aborts before building the HTTP request. Notion's API requires a Bearer integration token; the library fails fast with a clear message instead of receiving a 401 from the server. This is purely a local configuration check (strings.TrimSpace(c.Token) == "").

Source

Thrown at internal/notion/client.go:249

		if err != nil {
			return nil, fmt.Errorf("retrieve child data source %s: %w", resolvedID, err)
		}
		return &ResolvedDataSource{
			InputID:      identifier,
			DataSourceID: resolvedID,
			DataSource:   resolvedDS,
			Database:     db,
			ViewURL:      strings.TrimSpace(ref),
		}, nil
	}
}

func (c *Client) doRequest(ctx context.Context, method, path string, requestBody interface{}) ([]byte, error) {
	if c == nil {
		return nil, fmt.Errorf("notion client is nil")
	}
	if strings.TrimSpace(c.Token) == "" {
		return nil, fmt.Errorf("Notion token not configured")
	}
	httpClient := c.HTTPClient
	if httpClient == nil {
		httpClient = &http.Client{Timeout: DefaultTimeout}
	}

	var bodyReader io.Reader
	if requestBody != nil {
		payload, err := json.Marshal(requestBody)
		if err != nil {
			return nil, fmt.Errorf("marshal request body: %w", err)
		}
		bodyReader = bytes.NewReader(payload)
	}

	requestURL := path
	if !strings.HasPrefix(requestURL, "http://") && !strings.HasPrefix(requestURL, "https://") {
		requestURL = strings.TrimSuffix(c.BaseURL, "/") + path

View on GitHub (pinned to 71377f2769)

Solutions

  1. Export the token before running: export NOTION_TOKEN="ntn_..." (or set it in .env / deployment secrets).
  2. Pass the token explicitly to the client constructor and log a startup error if it is empty.
  3. Validate configuration at startup: if strings.TrimSpace(cfg.NotionToken) == "" { return errors.New("NOTION_TOKEN is required") }.
  4. Verify the secret is actually mounted in the runtime environment (docker inspect / kubectl describe pod), not just present locally.

Example fix

// before
client := notion.NewClient(os.Getenv("NOTION_TOKEN")) // silently empty

// after
token := os.Getenv("NOTION_TOKEN")
if strings.TrimSpace(token) == "" {
    return fmt.Errorf("NOTION_TOKEN must be set")
}
client := notion.NewClient(token)
Defensive patterns

Strategy: validation

Validate before calling

token := os.Getenv("NOTION_TOKEN")
if strings.TrimSpace(token) == "" {
    return fmt.Errorf("NOTION_TOKEN is required")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "Notion token not configured") {
    log.Fatal("set NOTION_TOKEN in your environment")
}

Prevention

When it happens

Trigger: Client constructed with an empty token: notion.NewClient("") or NewClient(os.Getenv("NOTION_TOKEN")) when NOTION_TOKEN is unset/empty; a config struct unmarshaled without the token key; token set only to spaces via env or config file.

Common situations: Missing NOTION_TOKEN env var in CI or .env not loaded; YAML/JSON config missing the notion.token key so it unmarshals as ""; Docker container deployed without the secret injected; renaming the env var without updating the loader.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/9dd5cb0fdf827ad5. Report an issue: GitHub.