gastownhall/beads · error

Jira URL not configured (set jira.url or JIRA_URL)

Error message

Jira URL not configured (set jira.url or JIRA_URL)

What it means

Tracker.Init validates configuration before constructing the Jira client, and the first mandatory value is the Jira instance base URL. It reads config key 'jira.url' and falls back to env var JIRA_URL; if the config lookup errors or yields an empty string, Init fails fast with this message naming both sources. No network calls have happened yet.

Source

Thrown at internal/jira/tracker.go:66

// PrimaryProjectKey returns the first configured project key.
func (t *Tracker) PrimaryProjectKey() string {
	if len(t.projectKeys) == 0 {
		return ""
	}
	return t.projectKeys[0]
}

func (t *Tracker) Name() string         { return "jira" }
func (t *Tracker) DisplayName() string  { return "Jira" }
func (t *Tracker) ConfigPrefix() string { return "jira" }

func (t *Tracker) Init(ctx context.Context, store storage.Storage) error {
	t.store = store

	jiraURL, err := t.getConfig(ctx, "jira.url", "JIRA_URL")
	if err != nil || jiraURL == "" {
		return fmt.Errorf("Jira URL not configured (set jira.url or JIRA_URL)")
	}
	t.jiraURL = jiraURL

	// Resolve project keys: use pre-set keys (from CLI), or fall back to config.
	if len(t.projectKeys) == 0 {
		pluralVal, _ := t.getConfig(ctx, "jira.projects", "JIRA_PROJECTS")
		singularVal, _ := t.getConfig(ctx, "jira.project", "JIRA_PROJECT")
		t.projectKeys = tracker.ResolveProjectIDs(nil, pluralVal, singularVal)
	}
	if len(t.projectKeys) == 0 {
		return fmt.Errorf("Jira project not configured (set jira.project, jira.projects, or JIRA_PROJECT)")
	}

	username, _ := t.getConfig(ctx, "jira.username", "JIRA_USERNAME")
	apiToken, err := t.getConfig(ctx, "jira.api_token", "JIRA_API_TOKEN")
	if err != nil || apiToken == "" {
		return fmt.Errorf("Jira API token not configured (set jira.api_token or JIRA_API_TOKEN)")
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set the JIRA_URL environment variable (e.g. export JIRA_URL=https://yourorg.atlassian.net).
  2. Or set the 'jira.url' key in the tracker config store.
  3. Verify the process environment actually contains the var (print env in the same context where the tracker runs).
  4. Check spelling/case of the env var and that secrets/config are mounted in CI/container environments.
  5. Re-run init and confirm subsequent required values (project, token) are also present to avoid the next failure in the chain.

Example fix

// before: nothing set
tracker.Init(ctx, store) // → error
// after
os.Setenv("JIRA_URL", "https://yourorg.atlassian.net")
err := tracker.Init(ctx, store)
Defensive patterns

Strategy: validation

Validate before calling

func requireEnv(keys ...string) error {
    for _, k := range keys {
        if os.Getenv(k) == "" {
            return fmt.Errorf("missing required env var %s", k)
        }
    }
    return nil
}
// usage: requireEnv("JIRA_URL") before tracker.Init

Try / catch

if err := tracker.Init(ctx, store); err != nil {
    if strings.Contains(err.Error(), "Jira URL not configured") {
        return fmt.Errorf("setup incomplete: export JIRA_URL=https://yourorg.atlassian.net")
    }
    return err
}

Prevention

When it happens

Trigger: Init(ctx, store) is called with neither the 'jira.url' config entry present nor the JIRA_URL environment variable set (or getConfig errors).

Common situations: Fresh install where config was never initialized; running in a container/scheduler that does not pass JIRA_URL through; typo'd env var name (JIRAURL, JIRA_HOST); config file present but loaded into the wrong storage/profile.

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/93ba442ecfdbf6c7. Report an issue: GitHub.