Description
IssueService.GetWatchersWithContext() panics with a nil pointer dereference when processing watchers that don't have an AccountID field. This commonly occurs with legacy Jira Server installations or watchers migrated from older Jira versions.
Version
- go-jira version: v1.17.0 (bug also exists in v1.12.0)
- Go version: go1.25.4
- Jira: Cloud/Server (any version with legacy watchers)
Steps to Reproduce
- Call
GetWatchersWithContext() on an issue that has watchers without AccountID
- Observe panic
Minimal Reproducible Example
package main
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
jira "github.com/andygrunwald/go-jira"
)
func main() {
// Mock server returns watcher without AccountID (legacy format)
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/rest/api/2/issue/TEST-123/watchers" {
response := map[string]interface{}{
"self": "https://example.atlassian.net/rest/api/2/issue/TEST-123/watchers",
"watchCount": 1,
"watchers": []map[string]interface{}{
{
"name": "olduser",
"displayName": "Old User",
"active": true,
// No accountId field
},
},
}
json.NewEncoder(w).Encode(response)
return
}
http.NotFound(w, r)
}))
defer server.Close()
client, _ := jira.NewClient(server.Client(), server.URL)
// This panics:
_, _, _ = client.Issue.GetWatchersWithContext(context.Background(), "TEST-123")
}
Expected Behavior
The function should either:
- Skip watchers without
AccountID gracefully, or
- Return an error, or
- Return the watcher data available (name, displayName)
Actual Behavior
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x756eb3]
goroutine 1 [running]:
github.com/andygrunwald/go-jira.(*IssueService).GetWatchersWithContext(...)
.../go-jira@v1.17.0/issue.go:1575
Root Cause
In issue.go at line ~1575:
func (s *IssueService) GetWatchersWithContext(ctx context.Context, issueID string) (*[]User, *Response, error) {
// ...
result := []User{}
for _, watcher := range watches.Watchers {
var user *User
if watcher.AccountID != "" {
user, resp, err = s.client.User.GetByAccountID(watcher.AccountID)
if err != nil {
return nil, resp, NewJiraError(resp, err)
}
}
result = append(result, *user) // ← PANIC: user is nil if AccountID is empty
}
return &result, resp, nil
}
When watcher.AccountID is empty, user remains nil, and dereferencing *user causes a panic.
Suggested Fix
Option 1: Skip watchers without AccountID
for _, watcher := range watches.Watchers {
if watcher.AccountID == "" {
continue // Skip legacy watchers
}
user, resp, err := s.client.User.GetByAccountID(watcher.AccountID)
if err != nil {
return nil, resp, NewJiraError(resp, err)
}
if user != nil {
result = append(result, *user)
}
}
Option 2: Handle both legacy and modern formats
for _, watcher := range watches.Watchers {
var user *User
var err error
if watcher.AccountID != "" {
user, resp, err = s.client.User.GetByAccountID(watcher.AccountID)
if err != nil {
return nil, resp, NewJiraError(resp, err)
}
} else if watcher.Name != "" {
// Fallback for legacy watchers - use watcher data directly
user = &User{
Name: watcher.Name,
DisplayName: watcher.DisplayName,
Active: watcher.Active,
}
}
if user != nil {
result = append(result, *user)
}
}
Additional Context
This issue affects environments with:
- Legacy Jira Server installations
- Migrated Jira Cloud instances with old watchers
- Any scenario where watchers were added before AccountID became mandatory
Probably related: #272
Description
IssueService.GetWatchersWithContext()panics with a nil pointer dereference when processing watchers that don't have anAccountIDfield. This commonly occurs with legacy Jira Server installations or watchers migrated from older Jira versions.Version
Steps to Reproduce
GetWatchersWithContext()on an issue that has watchers withoutAccountIDMinimal Reproducible Example
Expected Behavior
The function should either:
AccountIDgracefully, orActual Behavior
Root Cause
In
issue.goat line ~1575:When
watcher.AccountIDis empty,userremainsnil, and dereferencing*usercauses a panic.Suggested Fix
Option 1: Skip watchers without AccountID
Option 2: Handle both legacy and modern formats
Additional Context
This issue affects environments with:
Probably related: #272