gastownhall/beads · error
get issue %s: %w
Error message
get issue %s: %w
What it means
GetIssue wraps errors from doRequest for GET /issue/{key}. The HTTP layer failed: non-2xx status, auth failure, timeout, or network error. The issue key is embedded in the message so callers know which issue fetch failed. Also surfaces indirectly through CreateIssue, which calls GetIssue to hydrate the newly created issue.
Source
Thrown at internal/jira/client.go:241
startAt += len(result.Issues)
continue
}
if result.IsLast || result.NextPageToken == "" {
break
}
nextPageToken = result.NextPageToken
}
return allIssues, nil
}
// GetIssue fetches a single Jira issue by key (e.g., "PROJ-123").
func (c *Client) GetIssue(ctx context.Context, key string) (*Issue, error) {
apiURL := fmt.Sprintf("%s/issue/%s?fields=%s", c.apiBase(), url.PathEscape(key), searchFields)
body, err := c.doRequest(ctx, "GET", apiURL, nil)
if err != nil {
return nil, fmt.Errorf("get issue %s: %w", key, err)
}
var issue Issue
if err := json.Unmarshal(body, &issue); err != nil {
return nil, fmt.Errorf("parse issue response: %w", err)
}
return &issue, nil
}
// CreateIssue creates a new issue in Jira.
// fields should include "project", "summary", "issuetype", and optionally other fields.
func (c *Client) CreateIssue(ctx context.Context, fields map[string]interface{}) (*Issue, error) {
payload := map[string]interface{}{"fields": fields}
data, err := json.Marshal(payload)
if err != nil {
return nil, fmt.Errorf("marshal create request: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped HTTP error's status: 404 means verify the issue key exists and is visible to your account.
- For 401/403, regenerate the API token and confirm permissions on the project.
- For 404 on CreateIssue follow-up, verify APIVersion is correct so apiBase matches your deployment.
- For timeouts/transient errors, retry the fetch.
Example fix
// before
issue, err := client.GetIssue(ctx, key)
// after: tolerate transient failures on hydration
issue, err := client.GetIssue(ctx, key)
if err != nil && isTransient(err) {
issue, err = client.GetIssue(ctx, key)
} Defensive patterns
Strategy: try-catch
Validate before calling
var jiraKeyRe = regexp.MustCompile(`^[A-Z][A-Z0-9]*-\d+$`)
func validIssueKey(k string) bool { return jiraKeyRe.MatchString(k) }
// Also preflight permissions:
// GET /rest/api/3/mypermissions?permissions=BROWSE_PROJECTS Type guard
func isNotFound(err error) bool {
return err != nil && strings.Contains(err.Error(), "404")
} Try / catch
issue, err := client.GetIssue(ctx, key)
if err != nil {
switch {
case isNotFound(err):
return nil, fmt.Errorf("issue %s does not exist or is not visible: %w", key, err)
case errors.Is(err, context.DeadlineExceeded):
// transient: safe to retry
return client.GetIssue(ctx, key)
default:
return nil, err
}
} Prevention
- Validate issue key format before calling
- Confirm the account has Browse Projects permission for the key's project
- Keep API tokens current and scoped correctly
- Distinguish 404 (bad key/permission) from transient errors before retrying
When it happens
Trigger: Calling GetIssue (or CreateIssue completing then hydrating) with a key the server rejects: 404 for nonexistent key, 401/403 for auth or permission problems, 400 for malformed key, or transport failure.
Common situations: Typo'd issue key or wrong project prefix; API token revoked/expired; account lacks browse permission on the project; Jira Server instance lacking API v3; CreateIssue succeeding but the subsequent fetch hitting a transient error.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- search issues: %w
- fetch issue %s: %w
- create issue: %w
- failed to read response (attempt %d/%d): %w
- failed to list projects: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/736a940108aceb0e.
Report an issue: GitHub.