wtfutil/wtf · error · Error
%s
Error message
%s
What it means
The Pivotal client's apiv5 helper unmarshals every response body into an Error struct; if the payload contains a non-empty 'error' field, the client returns that server-provided message verbatim as a Go error. The displayed message is whatever Pivotal Tracker sent.
Source
Thrown at modules/pivotal/client.go:76
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-TrackerToken", apiToken)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// check if we received a Pivotal Error response
Err := Error{}
err = json.Unmarshal([]byte(string(data)), &Err)
if err == nil && Err.Error != "" {
return nil, fmt.Errorf("%s", Err.Error)
}
return &Resource{Response: &resp, Raw: string(data)}, nil
}
func (pivotal *PivotalClient) getCurrentUser() (*User, error) {
resource, err := pivotal.apiv5("me")
if err != nil {
return nil, err
}
user := User{}
err = json.Unmarshal([]byte(resource.Raw), &user)
if err != nil {
return nil, err
}
return &user, nil
}View on GitHub (pinned to bb838c1ccb)
Solutions
- Regenerate the Pivotal Tracker API token and update it in the client configuration
- Check the request parameters (project id, search query) — the error text itself names the invalid field
- Verify the token has access to the requested project/scope
- Inspect HTTP status alongside the message to distinguish auth vs validation vs rate-limit issues
Example fix
// before token: "stale-token" // after: generate at pivotaltracker.com/profile token: "<fresh X-TrackerToken value>"
Defensive patterns
Strategy: try-catch
Validate before calling
req, _ := http.NewRequest("GET", "https://www.pivotaltracker.com/services/v5/me", nil)
req.Header.Set("X-TrackerToken", token)
resp, err := http.DefaultClient.Do(req)
if err == nil && resp.StatusCode == 401 {
log.Println("Pivotal API token invalid or expired")
} Type guard
func pivotalAPIError(err error) (string, bool) {
var msg string
if err == nil {
return "", false
}
msg = err.Error()
return msg, msg != ""
} Try / catch
user, err := pivotal.getCurrentUser()
if err != nil {
var apiErr *pivotal.Error
if errors.As(err, &apiErr) {
log.Printf("Pivotal rejected the request: %v", err)
} else {
return err
}
} Prevention
- Regenerate and rotate the X-TrackerToken API key regularly
- Validate project IDs and search parameters before calling the API
- Confirm token scope covers the projects being queried
- Surface the server-provided error text to logs; Pivotal names the offending field
When it happens
Trigger: json.Unmarshal succeeds and Err.Error != "" in apiv5 — i.e. Pivotal Tracker responded with an error payload instead of the expected resource, during getCurrentUser or searchStories calls.
Common situations: Invalid or expired X-TrackerToken API key (401 body), malformed search query parameters (400 with description), requesting a project id the token cannot access (403), or rate limiting responses.
Related errors
AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03).
Data as JSON: /api/errors/c4ace1840585e660.
Report an issue: GitHub.